diff --git a/.eslintrc.js b/.eslintrc.js
index 584404e7..169b010 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -63,6 +63,10 @@
         'message': 'Use ES modules or cr.define() instead',
       },
     ],
+    'no-restricted-syntax': ['error', {
+      'selector': 'CallExpression[callee.object.name=JSON][callee.property.name=parse] > CallExpression[callee.object.name=JSON][callee.property.name=stringify]',
+      'message': 'Don\'t use JSON.parse(JSON.stringify(...)) to clone objects. Use structuredClone() instead.',
+    }],
     'no-throw-literal': 'error',
     'no-trailing-spaces': 'error',
     'no-var': 'error',
diff --git a/BUILD.gn b/BUILD.gn
index f0e0501..8ead6d3 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -8,7 +8,7 @@
 # you add a new build file, there must be some path of dependencies from this
 # file to your new one or GN won't know about it.
 
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/compiler/compiler.gni")
 import("//build/config/cronet/config.gni")
diff --git a/DEPS b/DEPS
index 39cbcb2..8b6d1a8 100644
--- a/DEPS
+++ b/DEPS
@@ -305,19 +305,19 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'src_internal_revision': '18eb78e3ff000e59a4071961b8049610345f59a8',
+  'src_internal_revision': 'd03e9b687fa3fb8a7deb59711777a7947b21252c',
   # 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': '77aeee3b81a5792a1338a28b1a24dc6c1ebada58',
+  'skia_revision': '2b218381e226d986a9b43789d8822b1ce4d80516',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '4eb5d72079603bd00a71b6b2a75a4f1ee7637e72',
+  'v8_revision': '9f07854eb0b779fa46b8b64bbc1da4e4a7572878',
   # 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': 'eebf069c1d98952c9cde6f4e5f81383736b10163',
+  'angle_revision': '32f209b83f782d396d9197744b897af421762726',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -380,7 +380,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': '448b931d9af81cee1f1bcf89672ccbad21a2513e',
+  'catapult_revision': 'c6db8519c02ae6a5afac0358c266dc3e5f2fd803',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling chromium_variations
   # and whatever else without interference from each other.
@@ -400,7 +400,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': '53b8fca44fd4432af2d1f671d2a7f231fe8038a4',
+  'devtools_frontend_revision': '1088b0366ce6feff0dab1f8ef102a6d2ee801ed3',
   # 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.
@@ -440,7 +440,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '3ec333906a355a569954ce4822852cda98dd7f23',
+  'dawn_revision': 'e2cd8aade99ffd2d2b97fe87fd43b08f22002692',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -840,7 +840,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    'f75c7cbd6dde5dd650d3052569eef08b0375ec10',
+    'c000cb71605baf6bfb5e5bcc6765491ccedc7369',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1211,7 +1211,7 @@
   # Tools used when building Chrome for Chrome OS. This affects both the Simple
   # Chrome workflow, as well as the chromeos-chrome ebuild.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c59189f1626e3a47873dfd17835da8c749c74a33',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'e2b86e44a8f0dda3b5ef536950ebf2c0d2021680',
       'condition': 'checkout_chromeos',
   },
 
@@ -1232,7 +1232,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'd82c19922e3cc3eb5693a8dda094e8c509de5c0b',
+      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'bfe3cc4e3041356c1d0fd615ab232ca7199a0d59',
       'condition': 'checkout_linux',
   },
 
@@ -1252,7 +1252,7 @@
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '30f443dc48bf5d1f37db4de38781a6e46e41169c',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '2c4d976019118bab0f3e12634570728fcb658494',
     'condition': 'checkout_src_internal',
   },
 
@@ -1515,7 +1515,7 @@
     Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'e8712e415627f22d0b00ebee8db99547077f39bd',
 
   'src/third_party/libaom/source/libaom':
-    Var('aomedia_git') + '/aom.git' + '@' +  '1dbe1c7fae2456f91ccc79fecb919e9ffea0727a',
+    Var('aomedia_git') + '/aom.git' + '@' +  '7b5f665231dfbcc5abc49d3b8d6d8826c75ce473',
 
   'src/third_party/libavif/src':
     Var('chromium_git') + '/external/github.com/AOMediaCodec/libavif.git' + '@' + Var('libavif_revision'),
@@ -1717,7 +1717,7 @@
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '79b45f60dfbe97cbbc8f8be3a3807ae186bfd60a',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '33063c9403c381f5411e1cddf8688a912529b4d9',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1902,7 +1902,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '1c407e0944032ac9877bf4e5e000acff7a591b73',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '9272771418491e6ec56d6ea11167d1d1cbf2b81f',
+    Var('webrtc_git') + '/src.git' + '@' + 'be04c98d6488fc86594424e39c16d849f8628e27',
 
   # 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.
@@ -2025,7 +2025,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'dqP4MAytg_KGHF8251vpp4VF_UJPwRVQt-5iBCxaZq4C',
+        'version': 'jM3cMoiS9C9nP7tepZFR_7jWsvW559uRXguyjPNRQWEC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4005,7 +4005,7 @@
 
   'src/components/optimization_guide/internal': {
       'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' +
-        'ea119ecea6b7de84e3d431216c0041f3a10c301c',
+        '8c7276b0b0c1b0aa55e922e6116e314116303e2a',
       'condition': 'checkout_src_internal',
   },
 
@@ -4059,7 +4059,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        'e93c9eb21e418da5953bd8239704c166ee419d57',
+        '1be9791237c4cd9def25d4b0276868f05aae5ba6',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/android_webview/browser/gfx/skia_output_surface_dependency_webview.cc b/android_webview/browser/gfx/skia_output_surface_dependency_webview.cc
index 3ca3c6c..c2c2cfd9 100644
--- a/android_webview/browser/gfx/skia_output_surface_dependency_webview.cc
+++ b/android_webview/browser/gfx/skia_output_surface_dependency_webview.cc
@@ -140,12 +140,6 @@
   LOG(ERROR) << "SkiaRenderer detected lost context.";
 }
 
-base::TimeDelta
-SkiaOutputSurfaceDependencyWebView::GetGpuBlockedTimeSinceLastSwap() {
-  // WebView doesn't track how long GPU thread was blocked
-  return base::TimeDelta();
-}
-
 void SkiaOutputSurfaceDependencyWebView::ScheduleDelayedGPUTaskFromGPUThread(
     base::OnceClosure task) {
   task_queue_->ScheduleIdleTask(std::move(task));
diff --git a/android_webview/browser/gfx/skia_output_surface_dependency_webview.h b/android_webview/browser/gfx/skia_output_surface_dependency_webview.h
index 021425b..4bfdad62 100644
--- a/android_webview/browser/gfx/skia_output_surface_dependency_webview.h
+++ b/android_webview/browser/gfx/skia_output_surface_dependency_webview.h
@@ -63,7 +63,6 @@
   void DidLoseContext(gpu::error::ContextLostReason reason,
                       const GURL& active_url) override;
 
-  base::TimeDelta GetGpuBlockedTimeSinceLastSwap() override;
   bool NeedsSupportForExternalStencil() override;
   bool IsUsingCompositorGpuThread() override;
 
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 5acaf484..d587e8e 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
@@ -361,6 +361,9 @@
                 ContentFeatures.EARLY_ESTABLISH_GPU_CHANNEL,
                 "Enable establishing the GPU channel early in renderer startup."),
         Flag.baseFeature(
+                ContentFeatures.GIN_JAVA_BRIDGE_MOJO,
+                "Enable the mojo based GIN java bridge implementation."),
+        Flag.baseFeature(
                 AwFeatures.WEBVIEW_X_REQUESTED_WITH_HEADER_CONTROL,
                 "Restricts insertion of XRequestedWith header on outgoing requests "
                         + "to those that have been allow-listed through the appropriate "
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 58b3b39..825baef1 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -2342,6 +2342,8 @@
     "wallpaper/wallpaper_metrics_manager.h",
     "wallpaper/wallpaper_pref_manager.cc",
     "wallpaper/wallpaper_pref_manager.h",
+    "wallpaper/wallpaper_time_of_day_scheduler.cc",
+    "wallpaper/wallpaper_time_of_day_scheduler.h",
     "wallpaper/wallpaper_utils/scored_sample.cc",
     "wallpaper/wallpaper_utils/scored_sample.h",
     "wallpaper/wallpaper_utils/wallpaper_calculated_colors.cc",
diff --git a/ash/ambient/ui/ambient_animation_progress_tracker.cc b/ash/ambient/ui/ambient_animation_progress_tracker.cc
index 18edeb6..646b637 100644
--- a/ash/ambient/ui/ambient_animation_progress_tracker.cc
+++ b/ash/ambient/ui/ambient_animation_progress_tracker.cc
@@ -13,6 +13,21 @@
 
 namespace ash {
 
+namespace {
+
+void MoveAnimation(base::flat_set<const lottie::Animation*>& from,
+                   base::flat_set<const lottie::Animation*>& to,
+                   const lottie::Animation* animation) {
+  if (to.contains(animation)) {
+    CHECK(!from.contains(animation));
+    return;
+  }
+  CHECK_EQ(from.erase(animation), 1u);
+  to.insert(animation);
+}
+
+}  // namespace
+
 AmbientAnimationProgressTracker::ImmutableParams::ImmutableParams() = default;
 
 AmbientAnimationProgressTracker::ImmutableParams::ImmutableParams(
@@ -31,7 +46,9 @@
 void AmbientAnimationProgressTracker::RegisterAnimation(
     lottie::Animation* animation) {
   DCHECK(animation);
-  DCHECK(!animation_observations_.IsObservingSource(animation));
+  if (animation_observations_.IsObservingSource(animation)) {
+    return;
+  }
   animation_observations_.AddObservation(animation);
   if (animation->GetPlaybackConfig()) {
     // The parameters verified here all concern "time" in the animation in some
@@ -43,7 +60,7 @@
   } else {
     DVLOG(4) << "Animation has not been Start()ed yet. Will be verified in "
                 "AnimationWillStartPlaying() later.";
-    uninitialized_animations_.insert(animation);
+    inactive_animations_.insert(animation);
   }
 }
 
@@ -98,10 +115,16 @@
   DCHECK(animation_observations_.IsObservingSource(
       const_cast<lottie::Animation*>(animation)));
   VerifyAnimationImmutableParams(*animation);
-  DCHECK(uninitialized_animations_.contains(animation));
-  DCHECK(!started_animations_.contains(animation));
-  uninitialized_animations_.erase(animation);
-  started_animations_.insert(animation);
+  MoveAnimation(/*from=*/inactive_animations_, /*to=*/started_animations_,
+                animation);
+}
+
+void AmbientAnimationProgressTracker::AnimationStopped(
+    const lottie::Animation* animation) {
+  CHECK(animation_observations_.IsObservingSource(
+      const_cast<lottie::Animation*>(animation)));
+  MoveAnimation(/*from=*/started_animations_, /*to=*/inactive_animations_,
+                animation);
 }
 
 void AmbientAnimationProgressTracker::AnimationIsDeleting(
@@ -111,7 +134,7 @@
   animation_observations_.RemoveObservation(
       const_cast<lottie::Animation*>(animation));
   started_animations_.erase(animation);
-  uninitialized_animations_.erase(animation);
+  inactive_animations_.erase(animation);
 }
 
 void AmbientAnimationProgressTracker::VerifyAnimationImmutableParams(
diff --git a/ash/ambient/ui/ambient_animation_progress_tracker.h b/ash/ambient/ui/ambient_animation_progress_tracker.h
index 7cd1b99..86d9ab5 100644
--- a/ash/ambient/ui/ambient_animation_progress_tracker.h
+++ b/ash/ambient/ui/ambient_animation_progress_tracker.h
@@ -77,6 +77,7 @@
  private:
   // lottie::AnimationObserver implementation:
   void AnimationWillStartPlaying(const lottie::Animation* animation) override;
+  void AnimationStopped(const lottie::Animation* animation) override;
   void AnimationIsDeleting(const lottie::Animation* animation) override;
 
   void VerifyAnimationImmutableParams(const lottie::Animation& animation) const;
@@ -87,7 +88,7 @@
   // Registered animations that have been Start()ed.
   base::flat_set<const lottie::Animation*> started_animations_;
   // Registered animations that have not been Start()ed yet.
-  base::flat_set<const lottie::Animation*> uninitialized_animations_;
+  base::flat_set<const lottie::Animation*> inactive_animations_;
 };
 
 }  // namespace ash
diff --git a/ash/ambient/ui/ambient_animation_progress_tracker_unittest.cc b/ash/ambient/ui/ambient_animation_progress_tracker_unittest.cc
index 8742ac93..4455bd3 100644
--- a/ash/ambient/ui/ambient_animation_progress_tracker_unittest.cc
+++ b/ash/ambient/ui/ambient_animation_progress_tracker_unittest.cc
@@ -186,5 +186,31 @@
   EXPECT_THAT(global_progress.current_timestamp, FloatEq(.25f));
 }
 
+TEST_F(AmbientAnimationProgressTrackerTest, AnimationRestarted) {
+  AmbientAnimationProgressTracker tracker;
+  auto animation =
+      std::make_unique<lottie::Animation>(CreateSkottie(/*duration_secs=*/10));
+  tracker.RegisterAnimation(animation.get());
+  animation->Start();
+  Paint(*animation);
+
+  clock_ += base::Seconds(5);
+  Paint(*animation);
+
+  ASSERT_TRUE(tracker.HasActiveAnimations());
+  EXPECT_THAT(tracker.GetGlobalProgress().current_timestamp, FloatEq(0.5f));
+
+  animation->Stop();
+  EXPECT_FALSE(tracker.HasActiveAnimations());
+  // Should be a no-op.
+  tracker.RegisterAnimation(animation.get());
+
+  animation->Start();
+  Paint(*animation);
+
+  ASSERT_TRUE(tracker.HasActiveAnimations());
+  EXPECT_THAT(tracker.GetGlobalProgress().current_timestamp, FloatEq(0.f));
+}
+
 }  // namespace
 }  // namespace ash
diff --git a/ash/app_list/views/app_list_view_pixeltest.cc b/ash/app_list/views/app_list_view_pixeltest.cc
index ffd24d62..8912be4 100644
--- a/ash/app_list/views/app_list_view_pixeltest.cc
+++ b/ash/app_list/views/app_list_view_pixeltest.cc
@@ -36,7 +36,7 @@
 
 namespace {
 
-using TestVariantsParam = std::tuple<bool, bool, bool, bool>;
+using TestVariantsParam = std::tuple<bool, bool, bool>;
 
 bool IsRtl(TestVariantsParam param) {
   return std::get<0>(param);
@@ -50,10 +50,6 @@
   return std::get<2>(param);
 }
 
-bool JellyEnabled(TestVariantsParam param) {
-  return std::get<3>(param);
-}
-
 std::string GenerateTestSuffix(
     const testing::TestParamInfo<TestVariantsParam>& info) {
   std::string suffix;
@@ -62,10 +58,6 @@
   suffix.append(IsDarkMode(info.param) ? "dark" : "light");
   suffix.append("_");
   suffix.append(IsTabletMode(info.param) ? "tablet" : "clamshell");
-  // Only add a suffix is Jelly is disabled so this is easier to delete.
-  if (!JellyEnabled(info.param)) {
-    suffix.append("PreJelly");
-  }
   return suffix;
 }
 
@@ -85,16 +77,8 @@
 
 class AppListViewPixelRTLTest
     : public AshTestBase,
-      public testing::WithParamInterface<
-          std::tuple<bool /*jelly_enabled=*/, bool /*is_rtl=*/>> {
+      public testing::WithParamInterface<std::tuple<bool /*is_rtl=*/>> {
  public:
-  // AshTestBase:
-  void SetUp() override {
-    scoped_features_.InitWithFeatureState(chromeos::features::kJelly,
-                                          JellyEnabled());
-    AshTestBase::SetUp();
-  }
-
   absl::optional<pixel_test::InitParams> CreatePixelTestInitParams()
       const override {
     pixel_test::InitParams init_params;
@@ -202,9 +186,7 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  bool JellyEnabled() const { return std::get<0>(GetParam()); }
-
-  bool IsRtl() const { return std::get<1>(GetParam()); }
+  bool IsRtl() const { return std::get<0>(GetParam()); }
 
  private:
   base::test::ScopedFeatureList scoped_features_;
@@ -212,7 +194,7 @@
 
 INSTANTIATE_TEST_SUITE_P(RTL,
                          AppListViewPixelRTLTest,
-                         testing::Combine(testing::Bool(), testing::Bool()));
+                         testing::Combine(testing::Bool()));
 
 // Verifies Answer Card search results under the clamshell mode.
 TEST_P(AppListViewPixelRTLTest, AnswerCardSearchResult) {
@@ -231,8 +213,7 @@
 
   UseFixedPlaceholderTextAndHideCursor(test_helper->GetSearchBoxView());
   EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
-      "bubble_launcher_answer_card_search_results",
-      /*revision_number=*/JellyEnabled() ? 9 : 7,
+      "bubble_launcher_answer_card_search_results", 10,
       GetAppListTestHelper()->GetBubbleView(),
       GetPrimaryShelf()->navigation_widget()));
 }
@@ -254,8 +235,7 @@
 
   UseFixedPlaceholderTextAndHideCursor(test_helper->GetSearchBoxView());
   EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
-      "bubble_launcher_url_search_results",
-      /*revision_number=*/JellyEnabled() ? 8 : 6,
+      "bubble_launcher_url_search_results", 9,
       GetAppListTestHelper()->GetBubbleView(),
       GetPrimaryShelf()->navigation_widget()));
 }
@@ -277,7 +257,7 @@
 
   UseFixedPlaceholderTextAndHideCursor(test_helper->GetSearchBoxView());
   EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
-      "bubble_launcher_ks_search_results", /*revision_number=*/0,
+      "bubble_launcher_ks_search_results", /*revision_number=*/2,
       GetAppListTestHelper()->GetBubbleView()));
 }
 
@@ -290,9 +270,7 @@
   UseFixedPlaceholderTextAndHideCursor(
       GetAppListTestHelper()->GetSearchBoxView());
   EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
-      "bubble_launcher_basics",
-      /*revision_number=*/JellyEnabled() ? 8 : 6,
-      GetAppListTestHelper()->GetBubbleView(),
+      "bubble_launcher_basics", 9, GetAppListTestHelper()->GetBubbleView(),
       GetPrimaryShelf()->navigation_widget()));
 }
 
@@ -313,8 +291,7 @@
                                 /*position=*/20);
 
   EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
-      "bubble_launcher_gradient_zone",
-      /*revision_number=*/JellyEnabled() ? 8 : 6,
+      "bubble_launcher_gradient_zone", 9,
       GetAppListTestHelper()->GetBubbleView(),
       GetPrimaryShelf()->navigation_widget()));
 }
@@ -331,9 +308,6 @@
   }
 
   void SetUp() override {
-    scoped_features_.InitWithFeatureState(chromeos::features::kJelly,
-                                          JellyEnabled(GetParam()));
-
     AssistantAshTestBase::SetUp();
 
     DarkLightModeController::Get()->SetDarkModeEnabledForTest(
@@ -357,7 +331,6 @@
                          AppListViewLauncherSearchIphTest,
                          testing::Combine(testing::Bool(),
                                           testing::Bool(),
-                                          testing::Bool(),
                                           testing::Bool()),
                          &GenerateTestSuffix);
 
@@ -385,8 +358,7 @@
 
 class AppListViewTabletPixelTest
     : public AshTestBase,
-      public testing::WithParamInterface<
-          std::tuple</*jelly_enabled=*/bool, /*rtl=*/bool>> {
+      public testing::WithParamInterface<std::tuple</*rtl=*/bool>> {
  public:
   // AshTestBase:
   absl::optional<pixel_test::InitParams> CreatePixelTestInitParams()
@@ -397,8 +369,6 @@
   }
 
   void SetUp() override {
-    scoped_features_.InitWithFeatureState(chromeos::features::kJelly,
-                                          IsJellyEnabled());
     AshTestBase::SetUp();
 
     Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
@@ -411,9 +381,7 @@
   }
 
  protected:
-  bool IsJellyEnabled() const { return std::get<0>(GetParam()); }
-
-  bool IsRtl() const { return std::get<1>(GetParam()); }
+  bool IsRtl() const { return std::get<0>(GetParam()); }
 
  private:
   base::test::ScopedFeatureList scoped_features_;
@@ -421,12 +389,12 @@
 
 INSTANTIATE_TEST_SUITE_P(RTL,
                          AppListViewTabletPixelTest,
-                         testing::Combine(testing::Bool(), testing::Bool()));
+                         testing::Combine(testing::Bool()));
 
 // Verifies the default layout for tablet mode launcher.
 TEST_P(AppListViewTabletPixelTest, Basic) {
   EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
-      "tablet_launcher_basics", 9,
+      "tablet_launcher_basics", 11,
       GetAppListTestHelper()->GetAppsContainerView()));
 }
 
@@ -447,7 +415,7 @@
   generator->MoveTouchBy(0, -40);
 
   EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
-      "tablet_launcher_top_gradient_zone", 7,
+      "tablet_launcher_top_gradient_zone", 9,
       GetAppListTestHelper()->GetAppsContainerView()));
 }
 
@@ -468,7 +436,7 @@
   generator->MoveTouchBy(0, -90);
 
   EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
-      "tablet_launcher_bottom_gradient_zone", 9,
+      "tablet_launcher_bottom_gradient_zone", 11,
       GetAppListTestHelper()->GetAppsContainerView()));
 }
 
@@ -478,8 +446,7 @@
   search_box_view->SetSearchBoxActive(true, ui::EventType::ET_UNKNOWN);
 
   EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
-      "search_box_view_active",
-      /*revision_number=*/IsJellyEnabled() ? 4 : 3, search_box_view));
+      "search_box_view_active", 5, search_box_view));
 }
 
 class AppListViewAssistantZeroStateTest
@@ -495,8 +462,7 @@
 
   void SetUp() override {
     scoped_features_.InitWithFeatureStates(
-        {{assistant::features::kEnableAssistantLearnMore, true},
-         {chromeos::features::kJelly, JellyEnabled(GetParam())}});
+        {{assistant::features::kEnableAssistantLearnMore, true}});
 
     AssistantAshTestBase::SetUp();
     SetNumberOfSessionsWhereOnboardingShown(
@@ -516,8 +482,7 @@
                          AppListViewAssistantZeroStateTest,
                          testing::Combine(/*IsRtl=*/testing::Bool(),
                                           /*IsDarkMode=*/testing::Bool(),
-                                          /*IsTabletMode=*/testing::Bool(),
-                                          /*JellyEnabled=*/testing::Bool()),
+                                          /*IsTabletMode=*/testing::Bool()),
                          &GenerateTestSuffix);
 
 TEST_P(AppListViewAssistantZeroStateTest, DISABLED_Basic) {
@@ -525,8 +490,7 @@
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
-      "app_list_view_assistant_zero_state",
-      /*revision_number=*/JellyEnabled(GetParam()) ? 5 : 4,
+      "app_list_view_assistant_zero_state", 5,
       page_view()->GetViewByID(AssistantViewID::kZeroStateView)));
 }
 
diff --git a/ash/ash_prefs.cc b/ash/ash_prefs.cc
index d351829..888039f 100644
--- a/ash/ash_prefs.cc
+++ b/ash/ash_prefs.cc
@@ -73,6 +73,7 @@
 #include "ash/user_education/user_education_controller.h"
 #include "ash/wallpaper/wallpaper_daily_refresh_scheduler.h"
 #include "ash/wallpaper/wallpaper_pref_manager.h"
+#include "ash/wallpaper/wallpaper_time_of_day_scheduler.h"
 #include "ash/wm/desks/desks_restore_util.h"
 #include "ash/wm/desks/templates/saved_desk_util.h"
 #include "ash/wm/float/tablet_mode_tuck_education.h"
@@ -156,6 +157,7 @@
   UsbPeripheralNotificationController::RegisterProfilePrefs(registry);
   VpnDetailedView::RegisterProfilePrefs(registry);
   WallpaperDailyRefreshScheduler::RegisterProfilePrefs(registry);
+  WallpaperTimeOfDayScheduler::RegisterProfilePrefs(registry);
   WallpaperPrefManager::RegisterProfilePrefs(registry);
   WindowCycleController::RegisterProfilePrefs(registry);
 
diff --git a/ash/assistant/ui/main_stage/assistant_zero_state_view.cc b/ash/assistant/ui/main_stage/assistant_zero_state_view.cc
index 30009027..8dbed74 100644
--- a/ash/assistant/ui/main_stage/assistant_zero_state_view.cc
+++ b/ash/assistant/ui/main_stage/assistant_zero_state_view.cc
@@ -157,7 +157,8 @@
 
   // Launcher search IPH view:
   iph_view_ = AddChildView(std::make_unique<LauncherSearchIphView>(
-      /*delegate=*/this, /*is_in_tablet_mode=*/delegate_->IsTabletMode()));
+      /*delegate=*/this, /*is_in_tablet_mode=*/delegate_->IsTabletMode(),
+      /*scoped_iph_session=*/nullptr, /*show_assistant_chip=*/false));
   iph_view_->SetID(AssistantViewID::kLauncherSearchIph);
   iph_view_->SetProperty(views::kMarginsKey, delegate_->IsTabletMode()
                                                  ? kIphMarginTabletModeDip
diff --git a/ash/assistant/ui/main_stage/launcher_search_iph_view.cc b/ash/assistant/ui/main_stage/launcher_search_iph_view.cc
index d26946c..6d02f8a 100644
--- a/ash/assistant/ui/main_stage/launcher_search_iph_view.cc
+++ b/ash/assistant/ui/main_stage/launcher_search_iph_view.cc
@@ -15,6 +15,7 @@
 #include "ash/style/typography.h"
 #include "base/functional/bind.h"
 #include "base/i18n/rtl.h"
+#include "base/rand_util.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_provider.h"
 #include "ui/events/event.h"
@@ -37,14 +38,21 @@
 constexpr int kMainLayoutBetweenChildSpacing = 16;
 constexpr int kActionContainerBetweenChildSpacing = 8;
 
+constexpr int kNumberOfQueryChipsWithAssistantChip = 3;
+constexpr int kNumberOfQueryChipsWithoutAssistantChip = 4;
+
 constexpr char16_t kTitleTextPlaceholder[] = u"Title text";
 constexpr char16_t kDescriptionTextPlaceholder[] = u"Description text";
 
-constexpr char16_t kChipOneQueryPlaceholder[] = u"Weather";
-constexpr char16_t kChipTwoQueryPlaceholder[] = u"1+1";
-constexpr char16_t kChipThreeQueryPlaceholder[] = u"5 cm in inches";
+constexpr char16_t kChipWeatherQueryPlaceholder[] = u"Weather";
+constexpr char16_t kChipShortcutQueryPlaceholder[] = u"Screen Saver";
+constexpr char16_t kChipCalculationQueryPlaceholder[] = u"50+96/5";
+constexpr char16_t kChipUnitConversionQueryPlaceholder[] = u"1 inch in cm";
+constexpr char16_t kChipTranslationQueryPlaceholder[] = u"Hello in Spanish";
+constexpr char16_t kChipDefinitionQueryPlaceholder[] = u"impromptu definition";
+constexpr char16_t kChipStockQueryPlaceholder[] = u"S&P 500";
 
-constexpr char16_t kAssistantButtonPlaceholder[] = u"Assistant";
+constexpr char16_t kAssistantButtonPlaceholder[] = u"Go to Assistant";
 
 constexpr gfx::RoundedCornersF kBackgroundRadiiClamshellLTR = {16, 4, 16, 16};
 
@@ -63,13 +71,28 @@
 
 constexpr int kBackgroundRadiusTablet = 16;
 
+std::vector<std::u16string> GetQueryChips(int num_of_chips) {
+  std::vector<std::u16string> chips = {
+      kChipWeatherQueryPlaceholder,     kChipShortcutQueryPlaceholder,
+      kChipCalculationQueryPlaceholder, kChipUnitConversionQueryPlaceholder,
+      kChipTranslationQueryPlaceholder, kChipDefinitionQueryPlaceholder,
+      kChipStockQueryPlaceholder};
+  CHECK_GE(static_cast<int>(chips.size()), num_of_chips);
+  base::RandomShuffle(chips.begin(), chips.end());
+  chips.resize(num_of_chips);
+  return chips;
+}
+
 }  // namespace
 
 LauncherSearchIphView::LauncherSearchIphView(
     Delegate* delegate,
     bool is_in_tablet_mode,
-    std::unique_ptr<ScopedIphSession> scoped_iph_session)
-    : delegate_(delegate), scoped_iph_session_(std::move(scoped_iph_session)) {
+    std::unique_ptr<ScopedIphSession> scoped_iph_session,
+    bool show_assistant_chip)
+    : delegate_(delegate),
+      scoped_iph_session_(std::move(scoped_iph_session)),
+      show_assistant_chip_(show_assistant_chip) {
   SetID(ViewId::kSelf);
 
   SetLayoutManager(std::make_unique<views::FillLayout>());
@@ -121,10 +144,13 @@
   actions_container->SetBetweenChildSpacing(
       kActionContainerBetweenChildSpacing);
 
+  // In Launcher zero state, we show 3 query chips + Assistant chip.
+  // In Assistant zero state, we show 4 query chips.
+  int num_of_chips = show_assistant_chip_
+                         ? kNumberOfQueryChipsWithAssistantChip
+                         : kNumberOfQueryChipsWithoutAssistantChip;
   int query_chip_view_id = ViewId::kChipStart;
-  for (const std::u16string& query :
-       {kChipOneQueryPlaceholder, kChipTwoQueryPlaceholder,
-        kChipThreeQueryPlaceholder}) {
+  for (const std::u16string& query : GetQueryChips(num_of_chips)) {
     ChipView* chip = actions_container->AddChildView(
         std::make_unique<ChipView>(ChipView::Type::kLarge));
     chip->SetText(query);
@@ -135,18 +161,20 @@
     query_chip_view_id++;
   }
 
-  views::View* spacer =
-      actions_container->AddChildView(std::make_unique<views::View>());
-  actions_container->SetFlexForView(spacer, 1);
+  if (show_assistant_chip_) {
+    views::View* spacer =
+        actions_container->AddChildView(std::make_unique<views::View>());
+    actions_container->SetFlexForView(spacer, 1);
 
-  ash::PillButton* assistant_button =
-      actions_container->AddChildView(std::make_unique<ash::PillButton>(
-          base::BindRepeating(&LauncherSearchIphView::OpenAssistantPage,
-                              weak_ptr_factory_.GetWeakPtr()),
-          kAssistantButtonPlaceholder));
-  assistant_button->SetID(ViewId::kAssistant);
-  assistant_button->SetPillButtonType(
-      PillButton::Type::kDefaultLargeWithoutIcon);
+    ash::PillButton* assistant_button =
+        actions_container->AddChildView(std::make_unique<ash::PillButton>(
+            base::BindRepeating(&LauncherSearchIphView::OpenAssistantPage,
+                                weak_ptr_factory_.GetWeakPtr()),
+            kAssistantButtonPlaceholder));
+    assistant_button->SetID(ViewId::kAssistant);
+    assistant_button->SetPillButtonType(
+        PillButton::Type::kDefaultLargeWithoutIcon);
+  }
 
   if (is_in_tablet_mode) {
     box_layout_view->SetBackground(views::CreateThemedRoundedRectBackground(
diff --git a/ash/assistant/ui/main_stage/launcher_search_iph_view.h b/ash/assistant/ui/main_stage/launcher_search_iph_view.h
index d04aadde..2f10a39b 100644
--- a/ash/assistant/ui/main_stage/launcher_search_iph_view.h
+++ b/ash/assistant/ui/main_stage/launcher_search_iph_view.h
@@ -45,8 +45,9 @@
 
   LauncherSearchIphView(
       Delegate* delegate,
-      bool is_in_tablet_mode = false,
-      std::unique_ptr<ScopedIphSession> scoped_iph_session = nullptr);
+      bool is_in_tablet_mode,
+      std::unique_ptr<ScopedIphSession> scoped_iph_session = nullptr,
+      bool show_assistant_chip = true);
   ~LauncherSearchIphView() override;
 
  private:
@@ -56,8 +57,11 @@
   void OpenAssistantPage();
 
   raw_ptr<Delegate> delegate_;
+
   std::unique_ptr<ScopedIphSession> scoped_iph_session_;
 
+  bool show_assistant_chip_ = false;
+
   base::WeakPtrFactory<LauncherSearchIphView> weak_ptr_factory_{this};
 };
 
diff --git a/ash/components/arc/arc_features_parser.cc b/ash/components/arc/arc_features_parser.cc
index 0359762..e908cea 100644
--- a/ash/components/arc/arc_features_parser.cc
+++ b/ash/components/arc/arc_features_parser.cc
@@ -4,14 +4,12 @@
 
 #include "ash/components/arc/arc_features_parser.h"
 
-#include <memory>
-
 #include "ash/components/arc/arc_util.h"
 #include "base/files/file_util.h"
 #include "base/functional/bind.h"
 #include "base/json/json_reader.h"
 #include "base/logging.h"
-#include "base/strings/string_util.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/values.h"
@@ -25,6 +23,24 @@
 constexpr const base::FilePath::CharType kArcFeaturesJsonFile[] =
     FILE_PATH_LITERAL("/etc/arc/features.json");
 
+enum class ParseResult {
+  kSuccess = 0,
+  kErrorParsingJson = 1,
+  kInvalidFeatureList = 2,
+  kInvalidUnavailableFeatureList = 3,
+  kInvalidPropertiesList = 4,
+  kMissingFingerprintProperty = 5,
+  kMissingSdkProperty = 6,
+  kMissingReleaseProperty = 7,
+  kMissingAbiListProperty = 8,
+  kMissingPlayStoreVersion = 9,
+  kMaxValue = kMissingPlayStoreVersion
+};
+
+void RecordParseResultHistogram(ParseResult status) {
+  base::UmaHistogramEnumeration("Arc.ArcFeatures.ParseResult", status);
+}
+
 base::RepeatingCallback<absl::optional<ArcFeatures>()>*
     g_arc_features_getter_for_testing = nullptr;
 
@@ -34,9 +50,11 @@
   auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(input_json);
   if (!parsed_json.has_value()) {
     LOG(ERROR) << "Error parsing feature JSON: " << parsed_json.error().message;
+    RecordParseResultHistogram(ParseResult::kErrorParsingJson);
     return absl::nullopt;
   } else if (!parsed_json->is_dict()) {
     LOG(ERROR) << "Error parsing feature JSON: Expected a dictionary.";
+    RecordParseResultHistogram(ParseResult::kErrorParsingJson);
     return absl::nullopt;
   }
 
@@ -46,6 +64,7 @@
   const base::Value::List* feature_list = dict.FindList("features");
   if (!feature_list) {
     LOG(ERROR) << "No feature list in JSON.";
+    RecordParseResultHistogram(ParseResult::kInvalidFeatureList);
     return absl::nullopt;
   }
   for (auto& feature_item : *feature_list) {
@@ -54,10 +73,12 @@
         feature_item.GetDict().FindInt("version");
     if (!feature_name || feature_name->empty()) {
       LOG(ERROR) << "Missing name in the feature.";
+      RecordParseResultHistogram(ParseResult::kInvalidFeatureList);
       return absl::nullopt;
     }
     if (!feature_version.has_value()) {
       LOG(ERROR) << "Missing version in the feature.";
+      RecordParseResultHistogram(ParseResult::kInvalidFeatureList);
       return absl::nullopt;
     }
     arc_features.feature_map.emplace(*feature_name, *feature_version);
@@ -67,17 +88,20 @@
   const base::Value::List* unavailable_feature_list =
       dict.FindList("unavailable_features");
   if (!unavailable_feature_list) {
+    RecordParseResultHistogram(ParseResult::kInvalidUnavailableFeatureList);
     LOG(ERROR) << "No unavailable feature list in JSON.";
     return absl::nullopt;
   }
   for (auto& feature_item : *unavailable_feature_list) {
     if (!feature_item.is_string()) {
       LOG(ERROR) << "Item in the unavailable feature list is not a string.";
+      RecordParseResultHistogram(ParseResult::kInvalidUnavailableFeatureList);
       return absl::nullopt;
     }
 
     if (feature_item.GetString().empty()) {
       LOG(ERROR) << "Missing name in the feature.";
+      RecordParseResultHistogram(ParseResult::kInvalidUnavailableFeatureList);
       return absl::nullopt;
     }
     arc_features.unavailable_features.emplace_back(feature_item.GetString());
@@ -87,6 +111,7 @@
   const base::Value::Dict* properties = dict.FindDict("properties");
   if (!properties) {
     LOG(ERROR) << "No properties in JSON.";
+    RecordParseResultHistogram(ParseResult::kInvalidPropertiesList);
     return absl::nullopt;
   }
 
@@ -94,6 +119,7 @@
   const std::string* fingerprint = properties->FindString(kFingerprintProperty);
   if (!fingerprint) {
     LOG(ERROR) << "Missing required build property " << kFingerprintProperty;
+    RecordParseResultHistogram(ParseResult::kMissingFingerprintProperty);
     return absl::nullopt;
   }
   arc_features.build_props.fingerprint = *fingerprint;
@@ -102,6 +128,7 @@
   const std::string* sdk_version = properties->FindString(kSdkProperty);
   if (!sdk_version) {
     LOG(ERROR) << "Missing required build property " << kSdkProperty;
+    RecordParseResultHistogram(ParseResult::kMissingSdkProperty);
     return absl::nullopt;
   }
   arc_features.build_props.sdk_version = *sdk_version;
@@ -110,6 +137,7 @@
   const std::string* release_version = properties->FindString(kReleaseProperty);
   if (!release_version) {
     LOG(ERROR) << "Missing required build property " << kReleaseProperty;
+    RecordParseResultHistogram(ParseResult::kMissingReleaseProperty);
     return absl::nullopt;
   }
   arc_features.build_props.release_version = *release_version;
@@ -124,6 +152,7 @@
   }
   if (!abi_list) {
     LOG(ERROR) << "Missing required abilist build property";
+    RecordParseResultHistogram(ParseResult::kMissingAbiListProperty);
     return absl::nullopt;
   }
   arc_features.build_props.abi_list = *abi_list;
@@ -132,10 +161,13 @@
   const std::string* play_version = dict.FindString("play_store_version");
   if (!play_version) {
     LOG(ERROR) << "No Play Store version in JSON.";
+    RecordParseResultHistogram(ParseResult::kMissingPlayStoreVersion);
     return absl::nullopt;
   }
   arc_features.play_store_version = *play_version;
 
+  RecordParseResultHistogram(ParseResult::kSuccess);
+
   return arc_features;
 }
 
diff --git a/ash/constants/ash_pref_names.h b/ash/constants/ash_pref_names.h
index 68cd0c7..768e3814 100644
--- a/ash/constants/ash_pref_names.h
+++ b/ash/constants/ash_pref_names.h
@@ -1117,6 +1117,15 @@
 inline constexpr char kWallpaperDailyRefreshSecondCheckTime[] =
     "ash.wallpaper_daily_refresh.second_check_time";
 
+// Prefs required by `ScheduledFeature` for the time of day wallpaper to follow
+// a sunset-to-sunrise schedule. Nothing in the system ultimately uses them.
+// TODO(b/309020921): Remove these once ScheduledFeature doesn't require prefs
+// to operate.
+inline constexpr char kWallpaperTimeOfDayStatus[] =
+    "ash.wallpaper_time_of_day.status";
+inline constexpr char kWallpaperTimeOfDayScheduleType[] =
+    "ash.wallpaper_time_of_day.schedule_type";
+
 // Boolean pref indicating whether a user has enabled the bluetooth adapter.
 inline constexpr char kUserBluetoothAdapterEnabled[] =
     "ash.user.bluetooth.adapter_enabled";
diff --git a/ash/frame/caption_buttons/frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc
index a9b7176..2042a10 100644
--- a/ash/frame/caption_buttons/frame_size_button_unittest.cc
+++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc
@@ -8,6 +8,7 @@
 #include "ash/display/screen_orientation_controller_test_api.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
+#include "ash/test/ash_test_util.h"
 #include "ash/wm/splitview/split_view_constants.h"
 #include "ash/wm/window_positioning_utils.h"
 #include "ash/wm/window_state.h"
@@ -184,7 +185,7 @@
 
   WindowState* window_state() { return window_state_; }
   const WindowState* window_state() const { return window_state_; }
-  views::Widget* GetWidget() const { return widget_; }
+  views::Widget* GetWidget() { return widget_; }
 
   views::FrameCaptionButton* minimize_button() { return minimize_button_; }
   views::FrameCaptionButton* size_button() { return size_button_; }
@@ -679,13 +680,8 @@
 
   void ShowMultitaskMenu(MultitaskMenuEntryType entry_type =
                              MultitaskMenuEntryType::kFrameSizeButtonHover) {
-    DCHECK(size_button());
-
-    views::NamedWidgetShownWaiter waiter(
-        views::test::AnyWidgetTestPasskey{},
-        std::string(kMultitaskMenuBubbleWidgetName));
-    static_cast<FrameSizeButton*>(size_button())->ShowMultitaskMenu(entry_type);
-    waiter.WaitIfNeededAndGet();
+    ShowAndWaitMultitaskMenuForWindow(
+        static_cast<FrameSizeButton*>(size_button()), entry_type);
   }
 };
 
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h
index 0247926..66aa75e8 100644
--- a/ash/shell_delegate.h
+++ b/ash/shell_delegate.h
@@ -178,6 +178,9 @@
   virtual void OpenFeedbackDialog(FeedbackSource source,
                                   const std::string& description_template) = 0;
 
+  // Calls browser service to open the profile manager.
+  virtual void OpenProfileManager() = 0;
+
   // Returns the last committed URL from the web contents if the given |window|
   // contains a browser frame, otherwise returns GURL::EmptyURL().
   virtual const GURL& GetLastCommittedURLForWindowIfAny(aura::Window* window);
diff --git a/ash/system/focus_mode/focus_mode_detailed_view.cc b/ash/system/focus_mode/focus_mode_detailed_view.cc
index 8c768271..5662732 100644
--- a/ash/system/focus_mode/focus_mode_detailed_view.cc
+++ b/ash/system/focus_mode/focus_mode_detailed_view.cc
@@ -74,6 +74,8 @@
 constexpr auto kTimerAdjustmentButtonSize = gfx::Size(63, 36);
 constexpr auto kTimerCountdownViewInsets = gfx::Insets::TLBR(0, 24, 12, 16);
 
+constexpr int kToggleButtonLeftPadding = 8;
+
 // Creates an `IconButton` with the formatting needed for the
 // `timer_setting_view_`'s timer adjustment buttons.
 std::unique_ptr<IconButton> CreateTimerAdjustmentButton(
@@ -512,10 +514,13 @@
           RoundedContainer::Behavior::kAllRounded));
   do_not_disturb_view_->SetProperty(views::kMarginsKey,
                                     kDisconnectedContainerMargins);
+  // `RoundedContainer` adds extra insets, so we need to remove those.
+  do_not_disturb_view_->SetBorderInsets(gfx::Insets());
 
   HoverHighlightView* toggle_row = do_not_disturb_view_->AddChildView(
       std::make_unique<HoverHighlightView>(/*listener=*/this));
   toggle_row->SetFocusBehavior(View::FocusBehavior::NEVER);
+  toggle_row->SetPreferredSize(gfx::Size(0, kToggleViewHeight));
 
   // Create the do not disturb icon and its label.
   auto icon = std::make_unique<views::ImageView>();
@@ -538,10 +543,17 @@
 
   toggle->SetIsOn(controller->turn_on_do_not_disturb());
   do_not_disturb_toggle_button_ = toggle.get();
-  toggle_row->AddRightView(toggle.release());
+  toggle_row->AddRightView(toggle.release(),
+                           views::CreateEmptyBorder(gfx::Insets::TLBR(
+                               0, kToggleButtonLeftPadding, 0, 0)));
 
-  // TODO(hongyulong): Add insets for the tri_view of the toggle row.
   toggle_row->SetExpandable(true);
+  toggle_row->tri_view()->SetInsets(kToggleViewInsets);
+  views::BoxLayout* toggle_view_tri_view_layout =
+      toggle_row->tri_view()->box_layout();
+  toggle_view_tri_view_layout->set_cross_axis_alignment(
+      views::BoxLayout::CrossAxisAlignment::kCenter);
+  toggle_view_tri_view_layout->InvalidateLayout();
 }
 
 void FocusModeDetailedView::OnDoNotDisturbToggleClicked() {
diff --git a/ash/system/message_center/ash_notification_view.h b/ash/system/message_center/ash_notification_view.h
index bfea0f2..0934c86 100644
--- a/ash/system/message_center/ash_notification_view.h
+++ b/ash/system/message_center/ash_notification_view.h
@@ -183,6 +183,7 @@
 
  private:
   friend class AshNotificationViewTestBase;
+  friend class MessageCenterMetricsUtilsTest;
   friend class NotificationGroupingControllerTest;
 
   // Customized title row for this notification view with added timestamp in
diff --git a/ash/system/message_center/metrics_utils.cc b/ash/system/message_center/metrics_utils.cc
index bd6e2ae0..fc265b51 100644
--- a/ash/system/message_center/metrics_utils.cc
+++ b/ash/system/message_center/metrics_utils.cc
@@ -9,6 +9,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/message_center/message_center.h"
@@ -40,9 +41,7 @@
   if (notifier_id.type != message_center::NotifierType::SYSTEM_COMPONENT)
     return false;
 
-  if (notifier_id.catalog_name == ash::NotificationCatalogName::kNone ||
-      notifier_id.catalog_name ==
-          ash::NotificationCatalogName::kTestCatalogName) {
+  if (notifier_id.catalog_name == ash::NotificationCatalogName::kNone) {
     return false;
   }
 
@@ -394,18 +393,34 @@
   }
 }
 
-void LogClickedActionButton(const std::string& notification_id, bool is_popup) {
-  auto type = GetNotificationType(notification_id);
-  if (!type.has_value())
+void LogClickedActionButton(const std::string& notification_id,
+                            bool is_popup,
+                            int button_index) {
+  auto* notification =
+      message_center::MessageCenter::Get()->FindVisibleNotificationById(
+          notification_id);
+  if (!notification) {
     return;
-
+  }
+  const auto type = GetNotificationType(*notification);
   if (is_popup) {
     UMA_HISTOGRAM_ENUMERATION(
-        "Notifications.Cros.Actions.Popup.ClickedActionButton", type.value());
+        "Notifications.Cros.Actions.Popup.ClickedActionButton", type);
   } else {
     UMA_HISTOGRAM_ENUMERATION(
-        "Notifications.Cros.Actions.Tray.ClickedActionButton", type.value());
+        "Notifications.Cros.Actions.Tray.ClickedActionButton", type);
   }
+
+  if (!ValidCatalogName(notification->notifier_id())) {
+    return;
+  }
+
+  const std::string histogram_base =
+      GetNotifierFrameworkNotificationHistogramBase(notification->pinned());
+  base::UmaHistogramEnumeration(
+      base::StringPrintf("%s.ClickedActionButton.%u", histogram_base.c_str(),
+                         button_index + 1),
+      notification->notifier_id().catalog_name);
 }
 
 void LogInlineReplySent(const std::string& notification_id, bool is_popup) {
diff --git a/ash/system/message_center/metrics_utils.h b/ash/system/message_center/metrics_utils.h
index b2164d6..7e99fe15 100644
--- a/ash/system/message_center/metrics_utils.h
+++ b/ash/system/message_center/metrics_utils.h
@@ -122,7 +122,9 @@
 void LogClickedBody(const std::string& notification_id, bool is_popup);
 
 // Logs a ClickedActionButton event.
-void LogClickedActionButton(const std::string& notification_id, bool is_popup);
+void LogClickedActionButton(const std::string& notification_id,
+                            bool is_popup,
+                            int button_index);
 
 // Logs an InlineReplySent event.
 ASH_EXPORT void LogInlineReplySent(const std::string& notification_id,
diff --git a/ash/system/message_center/metrics_utils_unittest.cc b/ash/system/message_center/metrics_utils_unittest.cc
index 8ee6fc1..a257b0f 100644
--- a/ash/system/message_center/metrics_utils_unittest.cc
+++ b/ash/system/message_center/metrics_utils_unittest.cc
@@ -6,10 +6,12 @@
 
 #include <memory>
 
+#include "ash/system/message_center/ash_notification_view.h"
 #include "ash/system/notification_center/notification_center_test_api.h"
 #include "ash/system/notification_center/notification_center_view.h"
 #include "ash/system/notification_center/notification_list_view.h"
 #include "ash/test/ash_test_base.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
@@ -18,6 +20,7 @@
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/public/cpp/notification.h"
 #include "ui/message_center/public/cpp/notifier_id.h"
+#include "ui/views/controls/button/label_button.h"
 #include "ui/views/widget/widget_utils.h"
 
 using message_center::Notification;
@@ -39,6 +42,9 @@
 constexpr char kPinnedSystemNotificationAddedHistogramName[] =
     "Ash.NotifierFramework.PinnedSystemNotification.Added";
 
+constexpr char kSystemNotificationClickedOnActionButton[] =
+    "Ash.NotifierFramework.SystemNotification.ClickedActionButton.";
+
 constexpr char kSystemNotificationPopupShownHistogramName[] =
     "Ash.NotifierFramework.SystemNotification.Popup.ShownCount";
 
@@ -184,8 +190,15 @@
   }
 
   // Get the popup notification view associated with `id`.
-  views::View* GetPopupNotificationView(const std::string& id) {
-    return notification_center_test_api_->GetPopupViewForId(id);
+  AshNotificationView* GetPopupNotificationView(const std::string& id) {
+    return static_cast<AshNotificationView*>(
+        notification_center_test_api_->GetPopupViewForId(id)->message_view());
+  }
+
+  views::View* GetActionButtonFromIndex(AshNotificationView* notification_view,
+                                        unsigned int index) {
+    CHECK_LT(index, notification_view->action_buttons().size());
+    return notification_view->action_buttons()[index];
   }
 
   void ClickView(views::View* view) {
@@ -456,17 +469,6 @@
 TEST_F(MessageCenterMetricsUtilsTest, RecordSystemNotificationAdded) {
   base::HistogramTester histograms;
 
-  // Create a system notification with `kTestCatalogName` for its catalog name.
-  const NotificationCatalogName test_catalog_name =
-      NotificationCatalogName::kTestCatalogName;
-  auto test_notification = CreateNotificationWithCatalogName(test_catalog_name);
-  message_center::MessageCenter::Get()->AddNotification(
-      std::move(test_notification));
-
-  // Check metrics are not recorded for `kTestCatalogName`.
-  histograms.ExpectBucketCount(kSystemNotificationAddedHistogramName,
-                               test_catalog_name, 0);
-
   // Create system notifications with a valid catalog name, one for a non-pinned
   // notification and one for a pinned one (e.g. Full Restore and Caps Lock).
   const NotificationCatalogName catalog_name =
@@ -589,4 +591,31 @@
                                catalog_name, 1);
 }
 
+TEST_F(MessageCenterMetricsUtilsTest, RecordCataloguedClickActionButton) {
+  base::HistogramTester histograms;
+  auto buttons = {message_center::ButtonInfo(u"Button 1"),
+                  message_center::ButtonInfo(u"Button 2"),
+                  message_center::ButtonInfo(u"Button 3"),
+                  message_center::ButtonInfo(u"Button 4")};
+
+  // Create a non-pinned system notification with a valid catalog name.
+  const NotificationCatalogName catalog_name =
+      NotificationCatalogName::kTestCatalogName;
+  auto notification = CreateNotificationWithCatalogName(catalog_name);
+  notification->set_buttons(buttons);
+
+  auto* message_center = message_center::MessageCenter::Get();
+  message_center->AddNotification(
+      std::make_unique<message_center::Notification>(*notification));
+
+  auto* notification_view = GetPopupNotificationView(notification->id());
+
+  for (unsigned int index = 0; index < buttons.size(); index++) {
+    ClickView(GetActionButtonFromIndex(notification_view, index));
+    histograms.ExpectBucketCount(kSystemNotificationClickedOnActionButton +
+                                     base::NumberToString(index + 1),
+                                 catalog_name, 1);
+  }
+}
+
 }  // namespace ash
diff --git a/ash/system/notification_center/notification_metrics_recorder.cc b/ash/system/notification_center/notification_metrics_recorder.cc
index f7bf071..6a43d52 100644
--- a/ash/system/notification_center/notification_metrics_recorder.cc
+++ b/ash/system/notification_center/notification_metrics_recorder.cc
@@ -46,7 +46,8 @@
   if (reply.has_value()) {
     metrics_utils::LogInlineReplySent(notification_id, is_popup);
   } else if (button_index.has_value()) {
-    metrics_utils::LogClickedActionButton(notification_id, is_popup);
+    metrics_utils::LogClickedActionButton(notification_id, is_popup,
+                                          button_index.value());
   } else {
     metrics_utils::LogClickedBody(notification_id, is_popup);
   }
diff --git a/ash/test/ash_test_util.cc b/ash/test/ash_test_util.cc
index 507d1da3f..3f5fed0f9 100644
--- a/ash/test/ash_test_util.cc
+++ b/ash/test/ash_test_util.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <vector>
 
+#include "ash/frame/non_client_frame_view_ash.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
@@ -22,8 +23,9 @@
 #include "base/scoped_observation.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/single_thread_task_runner.h"
+#include "chromeos/ui/frame/multitask_menu/multitask_menu.h"
+#include "chromeos/ui/frame/multitask_menu/multitask_menu_metrics.h"
 #include "ui/aura/client/aura_constants.h"
-#include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image.h"
@@ -32,6 +34,7 @@
 #include "ui/snapshot/snapshot_aura.h"
 #include "ui/views/controls/menu/menu_item_view.h"
 #include "ui/views/view_utils.h"
+#include "ui/views/widget/any_widget_observer.h"
 #include "ui/views/widget/widget.h"
 
 namespace ash {
@@ -238,4 +241,37 @@
   return MenuItemViewWithLabelWaiter(label).Wait();
 }
 
+chromeos::MultitaskMenu* ShowAndWaitMultitaskMenuForWindow(
+    absl::variant<aura::Window*, chromeos::FrameSizeButton*>
+        window_or_size_button,
+    chromeos::MultitaskMenuEntryType entry_type) {
+  // If a size button object is passed, use that. Otherwise retrieve it from the
+  // non client frame view ash.
+  chromeos::FrameSizeButton* size_button = nullptr;
+  if (absl::holds_alternative<chromeos::FrameSizeButton*>(
+          window_or_size_button)) {
+    size_button = absl::get<chromeos::FrameSizeButton*>(window_or_size_button);
+  } else {
+    aura::Window* window = absl::get<aura::Window*>(window_or_size_button);
+    CHECK(window);
+    auto* frame_view = NonClientFrameViewAsh::Get(window);
+    if (!frame_view) {
+      return nullptr;
+    }
+
+    size_button = views::AsViewClass<chromeos::FrameSizeButton>(
+        frame_view->GetHeaderView()->caption_button_container()->size_button());
+  }
+
+  views::NamedWidgetShownWaiter waiter(
+      views::test::AnyWidgetTestPasskey{},
+      std::string("MultitaskMenuBubbleWidget"));
+  size_button->ShowMultitaskMenu(entry_type);
+  views::WidgetDelegate* delegate =
+      waiter.WaitIfNeededAndGet()->widget_delegate();
+  auto* multitask_menu =
+      static_cast<chromeos::MultitaskMenu*>(delegate->AsDialogDelegate());
+  return multitask_menu;
+}
+
 }  // namespace ash
diff --git a/ash/test/ash_test_util.h b/ash/test/ash_test_util.h
index 5efbc57..f59a3dd 100644
--- a/ash/test/ash_test_util.h
+++ b/ash/test/ash_test_util.h
@@ -7,18 +7,22 @@
 
 #include <cstddef>
 
+#include "chromeos/ui/frame/caption_buttons/frame_size_button.h"
+#include "chromeos/ui/frame/multitask_menu/multitask_menu_metrics.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/aura/window.h"
 #include "ui/gfx/image/image_skia.h"
 
-namespace aura {
-class Window;
-}  // namespace aura
-
 namespace base {
 class FilePath;
 class TimeDelta;
 }  // namespace base
 
+namespace chromeos {
+class MultitaskMenu;
+}  // namespace chromeos
+
 namespace gfx {
 class Size;
 }  // namespace gfx
@@ -67,6 +71,16 @@
 // Returns the pointer to the first found target menu item view.
 views::MenuItemView* WaitForMenuItemWithLabel(const std::u16string& label);
 
+// Shows and returns the clamshell multitask menu which is anchored to the frame
+// size button. Some tests create their own caption button container and
+// therefore their own size button. We use that if it is passed, otherwise try
+// to fetch the size button from the non client frame view ash.
+chromeos::MultitaskMenu* ShowAndWaitMultitaskMenuForWindow(
+    absl::variant<aura::Window*, chromeos::FrameSizeButton*>
+        window_or_size_button,
+    chromeos::MultitaskMenuEntryType entry_type =
+        chromeos::MultitaskMenuEntryType::kFrameSizeButtonHover);
+
 }  // namespace ash
 
 #endif
diff --git a/ash/test_shell_delegate.h b/ash/test_shell_delegate.h
index 1d03a74d..ad1623e 100644
--- a/ash/test_shell_delegate.h
+++ b/ash/test_shell_delegate.h
@@ -97,6 +97,7 @@
   base::FilePath GetPrimaryUserDownloadsFolder() const override;
   void OpenFeedbackDialog(FeedbackSource source,
                           const std::string& description_template) override {}
+  void OpenProfileManager() override {}
   void SetLastCommittedURLForWindow(const GURL& url);
   version_info::Channel GetChannel() override;
   std::string GetVersionString() override;
diff --git a/ash/utility/haptics_util_unittest.cc b/ash/utility/haptics_util_unittest.cc
index 027c97f6..ef36405 100644
--- a/ash/utility/haptics_util_unittest.cc
+++ b/ash/utility/haptics_util_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
+#include "ash/test/ash_test_util.h"
 #include "ash/utility/haptics_tracking_test_input_controller.h"
 #include "ash/wm/desks/desk_animation_impl.h"
 #include "ash/wm/desks/desk_mini_view.h"
@@ -23,6 +24,9 @@
 #include "ash/wm/overview/overview_item.h"
 #include "ash/wm/overview/overview_session.h"
 #include "ash/wm/workspace/workspace_window_resizer.h"
+#include "chromeos/ui/frame/multitask_menu/multitask_button.h"
+#include "chromeos/ui/frame/multitask_menu/multitask_menu_view_test_api.h"
+#include "chromeos/ui/frame/multitask_menu/split_button_view.h"
 #include "ui/aura/window.h"
 #include "ui/events/devices/haptic_touchpad_effects.h"
 #include "ui/gfx/geometry/rect.h"
@@ -333,4 +337,50 @@
   ExitOverview();
 }
 
+TEST_F(HapticsUtilTest, HapticFeedbackForMultitaskMenu) {
+  auto input_controller =
+      std::make_unique<HapticsTrackingTestInputController>();
+
+  std::unique_ptr<aura::Window> window = CreateAppWindow();
+
+  // Show the clamshell multitask menu via hover. Test that kSnap feedback is
+  // sent.
+  chromeos::MultitaskMenu* multitask_menu = ShowAndWaitMultitaskMenuForWindow(
+      window.get(), chromeos::MultitaskMenuEntryType::kFrameSizeButtonHover);
+  ASSERT_TRUE(multitask_menu);
+  EXPECT_EQ(1, input_controller->GetSentHapticCount(
+                   HapticTouchpadEffect::kSnap,
+                   HapticTouchpadEffectStrength::kMedium));
+
+  // Test that the kSnap feedback is sent whenever we hover over one of the
+  // multitask menu buttons.
+  auto* event_generator = GetEventGenerator();
+  chromeos::MultitaskMenuViewTestApi test_api(
+      multitask_menu->multitask_menu_view());
+  event_generator->MoveMouseTo(
+      test_api.GetFloatButton()->GetBoundsInScreen().CenterPoint());
+  EXPECT_EQ(2, input_controller->GetSentHapticCount(
+                   HapticTouchpadEffect::kSnap,
+                   HapticTouchpadEffectStrength::kMedium));
+
+  event_generator->MoveMouseTo(
+      test_api.GetFullButton()->GetBoundsInScreen().CenterPoint());
+  EXPECT_EQ(3, input_controller->GetSentHapticCount(
+                   HapticTouchpadEffect::kSnap,
+                   HapticTouchpadEffectStrength::kMedium));
+
+  chromeos::SplitButtonView* half_button = test_api.GetHalfButton();
+  event_generator->MoveMouseTo(
+      half_button->GetLeftTopButton()->GetBoundsInScreen().CenterPoint());
+  EXPECT_EQ(4, input_controller->GetSentHapticCount(
+                   HapticTouchpadEffect::kSnap,
+                   HapticTouchpadEffectStrength::kMedium));
+
+  event_generator->MoveMouseTo(
+      half_button->GetRightBottomButton()->GetBoundsInScreen().CenterPoint());
+  EXPECT_EQ(5, input_controller->GetSentHapticCount(
+                   HapticTouchpadEffect::kSnap,
+                   HapticTouchpadEffectStrength::kMedium));
+}
+
 }  // namespace ash
diff --git a/ash/wallpaper/test_wallpaper_image_downloader.cc b/ash/wallpaper/test_wallpaper_image_downloader.cc
index cbc8eae..208881e4 100644
--- a/ash/wallpaper/test_wallpaper_image_downloader.cc
+++ b/ash/wallpaper/test_wallpaper_image_downloader.cc
@@ -13,11 +13,25 @@
 #include "components/account_id/account_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_unittest_util.h"
 #include "url/gurl.h"
 
 namespace ash {
 
-TestWallpaperImageDownloader::TestWallpaperImageDownloader() = default;
+namespace {
+
+// Downloading from the internet will create a different ImageSkia each time.
+// To simulate this same behavior, which WallpaperControllerImpl relies upon,
+// use a RepeatingClosure to generate a new image for each download. Returns a
+// high resolution image to ensure image resizing flow triggers.
+gfx::ImageSkia CreateTestImage(const GURL&) {
+  return gfx::test::CreateImageSkia(/*width=*/3000, /*height=*/3000);
+}
+
+}  // namespace
+
+TestWallpaperImageDownloader::TestWallpaperImageDownloader()
+    : image_generator_(base::BindRepeating(&CreateTestImage)) {}
 
 TestWallpaperImageDownloader::~TestWallpaperImageDownloader() = default;
 
@@ -27,7 +41,8 @@
     const absl::optional<std::string>& access_token,
     ImageDownloader::DownloadCallback callback) const {
   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), image_generator_.Run()));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), image_generator_.Run(url)));
 }
 
 void TestWallpaperImageDownloader::DownloadBackdropImage(
@@ -35,7 +50,8 @@
     const AccountId& account_id,
     ImageDownloader::DownloadCallback callback) const {
   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), image_generator_.Run()));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), image_generator_.Run(url)));
 }
 
 }  // namespace ash
diff --git a/ash/wallpaper/test_wallpaper_image_downloader.h b/ash/wallpaper/test_wallpaper_image_downloader.h
index 4d2e3ce..5c78f122 100644
--- a/ash/wallpaper/test_wallpaper_image_downloader.h
+++ b/ash/wallpaper/test_wallpaper_image_downloader.h
@@ -13,7 +13,6 @@
 #include "base/functional/callback.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/image/image_skia.h"
-#include "ui/gfx/image/image_unittest_util.h"
 
 class AccountId;
 class GURL;
@@ -30,7 +29,7 @@
 
   ~TestWallpaperImageDownloader() override;
 
-  using ImageGenerator = base::RepeatingCallback<gfx::ImageSkia()>;
+  using ImageGenerator = base::RepeatingCallback<gfx::ImageSkia(const GURL&)>;
   void set_image_generator(ImageGenerator image_generator) {
     image_generator_ = image_generator;
   }
@@ -48,14 +47,7 @@
       ImageDownloader::DownloadCallback callback) const override;
 
  private:
-  // Downloading from the internet will create a different ImageSkia each time.
-  // To simulate this same behavior, which WallpaperControllerImpl relies upon,
-  // use a RepeatingClosure to generate a new image for each download. Returns a
-  // high resolution image to ensure image resizing flow triggers.
-  ImageGenerator image_generator_ =
-      base::BindRepeating(gfx::test::CreateImageSkia,
-                          /*width=*/3000,
-                          /*height=*/3000);
+  ImageGenerator image_generator_;
 };
 
 }  // namespace ash
diff --git a/ash/wallpaper/wallpaper_controller_impl.cc b/ash/wallpaper/wallpaper_controller_impl.cc
index efb8071..7f061f9 100644
--- a/ash/wallpaper/wallpaper_controller_impl.cc
+++ b/ash/wallpaper/wallpaper_controller_impl.cc
@@ -276,10 +276,10 @@
 // returned `WallpaperInfo`. Returns nullptr on failure.
 std::unique_ptr<WallpaperInfo> CreateOnlineWallpaperInfo(
     const OnlineWallpaperParams& params,
+    const ScheduledFeature& scheduled_feature,
     const char* source) {
   const OnlineWallpaperVariant* selected_variant = FirstValidVariant(
-      params.variants,
-      Shell::Get()->dark_light_mode_controller()->current_checkpoint());
+      params.variants, scheduled_feature.current_checkpoint());
   if (!selected_variant) {
     LOG(ERROR) << "Failed to select online wallpaper variant from " << source;
     return nullptr;
@@ -764,8 +764,8 @@
     return;
   }
 
-  std::unique_ptr<WallpaperInfo> new_info =
-      CreateOnlineWallpaperInfo(params, __func__);
+  std::unique_ptr<WallpaperInfo> new_info = CreateOnlineWallpaperInfo(
+      params, GetScheduleForOnlineWallpaper(params.collection_id), __func__);
   if (!new_info) {
     std::move(callback).Run(/*success=*/false);
     return;
@@ -908,8 +908,8 @@
 
 bool WallpaperControllerImpl::IsTimeOfDayWallpaper() const {
   return current_wallpaper_ &&
-         current_wallpaper_->wallpaper_info().collection_id ==
-             wallpaper_constants::kTimeOfDayWallpaperCollectionId;
+         ::ash::IsTimeOfDayWallpaper(
+             current_wallpaper_->wallpaper_info().collection_id);
 }
 
 void WallpaperControllerImpl::SetDefaultWallpaper(
@@ -1471,6 +1471,10 @@
   shell->overview_controller()->AddObserver(this);
   shell->dark_light_mode_controller()->AddCheckpointObserver(this);
   daily_refresh_scheduler_ = std::make_unique<WallpaperDailyRefreshScheduler>();
+  time_of_day_scheduler_ = std::make_unique<WallpaperTimeOfDayScheduler>();
+  if (!time_of_day_scheduler_observation_.IsObserving()) {
+    time_of_day_scheduler_observation_.Observe(time_of_day_scheduler_.get());
+  }
   if (!daily_refresh_observation_.IsObserving()) {
     daily_refresh_observation_.Observe(daily_refresh_scheduler_.get());
   }
@@ -1482,6 +1486,7 @@
   shell->overview_controller()->RemoveObserver(this);
   shell->dark_light_mode_controller()->RemoveCheckpointObserver(this);
   daily_refresh_observation_.Reset();
+  time_of_day_scheduler_observation_.Reset();
 }
 
 void WallpaperControllerImpl::OnWallpaperResized() {
@@ -1601,7 +1606,8 @@
     return;
   }
 
-  if (!IsOnlineWallpaper(info.type)) {
+  if (!IsOnlineWallpaper(info.type) ||
+      src != &GetScheduleForOnlineWallpaper(info.collection_id)) {
     return;
   }
 
@@ -1909,8 +1915,8 @@
     return;
   }
 
-  std::unique_ptr<WallpaperInfo> new_info =
-      CreateOnlineWallpaperInfo(*params, __func__);
+  std::unique_ptr<WallpaperInfo> new_info = CreateOnlineWallpaperInfo(
+      *params, GetScheduleForOnlineWallpaper(params->collection_id), __func__);
   if (!new_info) {
     return;
   }
@@ -2988,4 +2994,13 @@
   return is_default_oobe_flow || is_add_person_flow;
 }
 
+const ScheduledFeature& WallpaperControllerImpl::GetScheduleForOnlineWallpaper(
+    const std::string& collection_id) const {
+  if (::ash::IsTimeOfDayWallpaper(collection_id)) {
+    return *time_of_day_scheduler_;
+  } else {
+    return *Shell::Get()->dark_light_mode_controller();
+  }
+}
+
 }  // namespace ash
diff --git a/ash/wallpaper/wallpaper_controller_impl.h b/ash/wallpaper/wallpaper_controller_impl.h
index cfa498e..cb82b60 100644
--- a/ash/wallpaper/wallpaper_controller_impl.h
+++ b/ash/wallpaper/wallpaper_controller_impl.h
@@ -31,6 +31,7 @@
 #include "ash/wallpaper/online_wallpaper_variant_info_fetcher.h"
 #include "ash/wallpaper/wallpaper_blur_manager.h"
 #include "ash/wallpaper/wallpaper_file_manager.h"
+#include "ash/wallpaper/wallpaper_time_of_day_scheduler.h"
 #include "ash/wallpaper/wallpaper_utils/wallpaper_calculated_colors.h"
 #include "ash/webui/personalization_app/mojom/personalization_app.mojom-forward.h"
 #include "ash/wm/overview/overview_observer.h"
@@ -407,6 +408,10 @@
     return daily_refresh_scheduler_.get();
   }
 
+  raw_ptr<WallpaperTimeOfDayScheduler> time_of_day_scheduler_for_testing() {
+    return time_of_day_scheduler_.get();
+  }
+
  private:
   friend class WallpaperControllerTestBase;
   friend class WallpaperControllerTestApi;
@@ -731,6 +736,9 @@
   // Returns whether session state is oobe or the oobe ui dialog is visible.
   bool IsOobeState() const;
 
+  const ScheduledFeature& GetScheduleForOnlineWallpaper(
+      const std::string& collection_id) const;
+
   bool is_session_active_ = false;
 
   OobeDialogState oobe_state_ = OobeDialogState::HIDDEN;
@@ -827,6 +835,10 @@
   // Provides signals to trigger wallpaper daily refresh.
   std::unique_ptr<WallpaperDailyRefreshScheduler> daily_refresh_scheduler_;
 
+  // Provides signal for when time-of-day wallpapers should change. Ignored if
+  // any other wallpaper collection is active.
+  std::unique_ptr<WallpaperTimeOfDayScheduler> time_of_day_scheduler_;
+
   scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
 
   ScopedSessionObserver scoped_session_observer_{this};
@@ -838,6 +850,10 @@
                           ScheduledFeature::CheckpointObserver>
       daily_refresh_observation_{this};
 
+  base::ScopedObservation<ScheduledFeature,
+                          ScheduledFeature::CheckpointObserver>
+      time_of_day_scheduler_observation_{this};
+
   std::unique_ptr<ui::CompositorLock> compositor_lock_;
 
   std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index a7e5857..872971a 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -41,6 +41,7 @@
 #include "ash/wallpaper/wallpaper_constants.h"
 #include "ash/wallpaper/wallpaper_daily_refresh_scheduler.h"
 #include "ash/wallpaper/wallpaper_pref_manager.h"
+#include "ash/wallpaper/wallpaper_time_of_day_scheduler.h"
 #include "ash/wallpaper/wallpaper_utils/wallpaper_file_utils.h"
 #include "ash/wallpaper/wallpaper_utils/wallpaper_resizer.h"
 #include "ash/webui/personalization_app/proto/backdrop_wallpaper.pb.h"
@@ -48,6 +49,7 @@
 #include "ash/wm/window_cycle/window_cycle_controller.h"
 #include "ash/wm/window_state.h"
 #include "base/command_line.h"
+#include "base/containers/flat_map.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/bind.h"
@@ -90,6 +92,7 @@
 #include "ui/gfx/codec/jpeg_codec.h"
 #include "ui/gfx/color_analysis.h"
 #include "ui/gfx/image/image_skia_rep.h"
+#include "ui/gfx/image/image_unittest_util.h"
 #include "ui/views/view_tracker.h"
 #include "ui/views/widget/widget.h"
 
@@ -159,6 +162,18 @@
 const std::string kFakeGooglePhotosAlbumId = "fake_album";
 const std::string kFakeGooglePhotosPhotoId = "fake_photo";
 
+// For checking that the wallpaper changes at approximately the correct time
+// when the "auto" schedule is enabled. The sunrise/set times specified in
+// `WallpaperControllerAutoScheduleTest` are just approximate and do not occur
+// exactly on the hour specified.
+MATCHER_P(WallpaperChangeTimeNear, hours_elapsed_since_test_start, "") {
+  static constexpr base::TimeDelta kTolerance = base::Minutes(5);
+  base::TimeDelta expected_duration_since_test_start =
+      base::Hours(hours_elapsed_since_test_start);
+  return expected_duration_since_test_start - kTolerance <= arg &&
+         arg <= expected_duration_since_test_start + kTolerance;
+}
+
 // Creates an image of size |size|.
 gfx::ImageSkia CreateImage(int width, int height, SkColor color) {
   SkBitmap bitmap;
@@ -393,6 +408,58 @@
   bool is_in_wallpaper_preview_ = false;
 };
 
+// Runs until the next time the wallpaper changes.
+class WallpaperChangedBarrier : public WallpaperControllerObserver {
+ public:
+  WallpaperChangedBarrier(WallpaperController* controller,
+                          base::test::TaskEnvironment* task_environment)
+      : task_environment_(task_environment) {
+    CHECK(task_environment_);
+    controller_observation_.Observe(controller);
+  }
+  WallpaperChangedBarrier(const WallpaperChangedBarrier&) = delete;
+  WallpaperChangedBarrier& operator=(const WallpaperChangedBarrier&) = delete;
+  ~WallpaperChangedBarrier() override = default;
+
+  // WallpaperControllerObserver:
+  void OnWallpaperChanged() override { wallpaper_changed_ = true; }
+
+  bool RunUntilNextWallpaperChange() {
+    wallpaper_changed_ = false;
+    while (!wallpaper_changed_) {
+      RunAllTasksUntilIdle();
+      base::TimeDelta delay_until_next_task =
+          task_environment_->NextMainThreadPendingTaskDelay();
+      if (delay_until_next_task == base::TimeDelta::Max()) {
+        // Technically, a delayed task on a different thread than "main" could
+        // trigger a wallpaper change but that is currently not the case.
+        return false;
+      }
+      task_environment_->FastForwardBy(delay_until_next_task);
+    }
+    return true;
+  }
+
+ private:
+  base::ScopedObservation<WallpaperController, WallpaperControllerObserver>
+      controller_observation_{this};
+  const raw_ptr<base::test::TaskEnvironment> task_environment_;
+  bool wallpaper_changed_ = false;
+};
+
+// Returns the image in `backdrop_image_data` whose `image_url` matches `url`,
+// or nullptr if no match is found.
+const backdrop::Image* GetImageMatchingUrl(
+    const GURL& url,
+    const std::vector<backdrop::Image>& backdrop_image_data) {
+  for (const backdrop::Image& image : backdrop_image_data) {
+    if (image.image_url() == url.spec()) {
+      return &image;
+    }
+  }
+  return nullptr;
+}
+
 // Returns the time of day wallpapers in order of light, morning, late
 // afternoon, and dark.
 std::vector<backdrop::Image> TimeOfDayImageSet() {
@@ -941,14 +1008,22 @@
   }
 
   void SetSimulatedStartTime(base::Time simulated_start_time) {
-    // Turn "auto" schedule off first to kill any internal timers within
-    // `dark_light_mode_controller` or `geolocation_controller` before passing
-    // them a new clock.
+    // Turn "auto" schedule off first to kill any internal timers within these
+    // objects before passing them a new clock.
+    WallpaperTimeOfDayScheduler& time_of_day_scheduler =
+        *Shell::Get()
+             ->wallpaper_controller()
+             ->time_of_day_scheduler_for_testing();
     Shell::Get()->dark_light_mode_controller()->SetAutoScheduleEnabled(false);
+    time_of_day_scheduler.SetScheduleType(ScheduleType::kNone);
+
     simulated_start_time_ = simulated_start_time;
     Shell::Get()->geolocation_controller()->SetClockForTesting(this);
     Shell::Get()->dark_light_mode_controller()->SetClockForTesting(this);
+    time_of_day_scheduler.SetClockForTesting(this);
+
     Shell::Get()->dark_light_mode_controller()->SetAutoScheduleEnabled(true);
+    time_of_day_scheduler.SetScheduleType(ScheduleType::kSunsetToSunrise);
   }
 
   const raw_ptr<base::test::TaskEnvironment> task_environment_;
@@ -4697,6 +4772,86 @@
   EXPECT_EQ(actual.date, original_timestamp);
 }
 
+TEST_P(WallpaperControllerAutoScheduleTest,
+       UpdateTimeOfDayWallpaperWithAutoColorModeOff) {
+  static constexpr gfx::Size kTestImageSize = gfx::Size(100, 100);
+  static constexpr SkColor kSunriseImageColor = SK_ColorRED;
+  static constexpr SkColor kMorningImageColor = SK_ColorGREEN;
+  static constexpr SkColor kLateAfternoonImageColor = SK_ColorBLUE;
+  static constexpr SkColor kSunsetImageColor = SK_ColorYELLOW;
+
+  if (!IsTimeOfDayEnabled()) {
+    return;
+  }
+  const auto backdrop_image_data = TimeOfDayImageSet();
+  client_.AddCollection(wallpaper_constants::kTimeOfDayWallpaperCollectionId,
+                        backdrop_image_data);
+  const base::flat_map<backdrop::Image_ImageType, gfx::ImageSkia> test_images =
+      {{backdrop::Image::IMAGE_TYPE_LIGHT_MODE,
+        CreateSolidColorTestImage(kTestImageSize, kSunriseImageColor)},
+       {backdrop::Image::IMAGE_TYPE_MORNING_MODE,
+        CreateSolidColorTestImage(kTestImageSize, kMorningImageColor)},
+       {backdrop::Image::IMAGE_TYPE_LATE_AFTERNOON_MODE,
+        CreateSolidColorTestImage(kTestImageSize, kLateAfternoonImageColor)},
+       {backdrop::Image::IMAGE_TYPE_DARK_MODE,
+        CreateSolidColorTestImage(kTestImageSize, kSunsetImageColor)}};
+  test_wallpaper_image_downloader()->set_image_generator(
+      base::BindLambdaForTesting([backdrop_image_data,
+                                  test_images](const GURL& url) {
+        const backdrop::Image* match_found =
+            GetImageMatchingUrl(url, backdrop_image_data);
+        return match_found
+                   ? test_images.at(match_found->image_type())
+                   : CreateSolidColorTestImage(kTestImageSize, SK_ColorBLACK);
+      }));
+
+  SimulateUserLogin(kAccountId1);
+  Shell::Get()->dark_light_mode_controller()->SetAutoScheduleEnabled(false);
+
+  OnlineWallpaperParams params(
+      kAccountId1, wallpaper_constants::kTimeOfDayWallpaperCollectionId,
+      WALLPAPER_LAYOUT_CENTER_CROPPED,
+      /*preview_mode=*/false, /*from_user=*/true,
+      /*daily_refresh_enabled=*/false,
+      wallpaper_constants::kDefaultTimeOfDayWallpaperUnitId, /*variants=*/{});
+  for (const backdrop::Image& backdrop_image : backdrop_image_data) {
+    params.variants.emplace_back(backdrop_image.asset_id(),
+                                 GURL(backdrop_image.image_url()),
+                                 backdrop_image.image_type());
+  }
+
+  const auto wallpaper_has_color = [this](SkColor color) {
+    return gfx::test::AreImagesClose(
+        gfx::Image(controller_->GetWallpaper()),
+        gfx::Image(CreateSolidColorTestImage(controller_->GetWallpaper().size(),
+                                             color)),
+        /*max_deviation=*/1);
+  };
+  // Midnight
+  base::test::TestFuture<bool> future;
+  controller_->SetOnlineWallpaper(params, future.GetCallback());
+  ASSERT_TRUE(future.Get());
+  EXPECT_TRUE(wallpaper_has_color(kSunsetImageColor));
+
+  WallpaperChangedBarrier barrier(controller_, task_environment());
+  // Sunrise. 7 AM.
+  ASSERT_TRUE(barrier.RunUntilNextWallpaperChange());
+  EXPECT_THAT(Now() - simulated_start_time_, WallpaperChangeTimeNear(7));
+  EXPECT_TRUE(wallpaper_has_color(kSunriseImageColor));
+  // Morning. 11 AM.
+  ASSERT_TRUE(barrier.RunUntilNextWallpaperChange());
+  EXPECT_THAT(Now() - simulated_start_time_, WallpaperChangeTimeNear(11));
+  EXPECT_TRUE(wallpaper_has_color(kMorningImageColor));
+  // Sunrise. 5 PM.
+  ASSERT_TRUE(barrier.RunUntilNextWallpaperChange());
+  EXPECT_THAT(Now() - simulated_start_time_, WallpaperChangeTimeNear(17));
+  EXPECT_TRUE(wallpaper_has_color(kLateAfternoonImageColor));
+  // Sunrise. 7 PM.
+  ASSERT_TRUE(barrier.RunUntilNextWallpaperChange());
+  EXPECT_THAT(Now() - simulated_start_time_, WallpaperChangeTimeNear(19));
+  EXPECT_TRUE(wallpaper_has_color(kSunsetImageColor));
+}
+
 TEST_P(WallpaperControllerTest,
        UpdateWallpaperOnScheduleCheckpointChanged_WithReplacedAsset) {
   SimulateUserLogin(kAccountId1);
@@ -4806,7 +4961,7 @@
   EXPECT_TRUE(pref_manager_->SetUserWallpaperInfo(kAccountId1, local_info));
   // Simulate a failure in image downloading.
   test_wallpaper_image_downloader()->set_image_generator(
-      base::BindLambdaForTesting([]() { return gfx::ImageSkia(); }));
+      base::BindLambdaForTesting([](const GURL&) { return gfx::ImageSkia(); }));
 
   // Switch to light mode and simulate schedule checkpoint change to reflect
   // light mode.
@@ -4914,7 +5069,7 @@
   // still succeeds because the previous call to |SetOnlineWallpaper()| has
   // saved the file.
   test_wallpaper_image_downloader()->set_image_generator(
-      base::BindLambdaForTesting([]() { return gfx::ImageSkia(); }));
+      base::BindLambdaForTesting([](const GURL&) { return gfx::ImageSkia(); }));
   ClearWallpaperCount();
   base::RunLoop run_loop;
   controller_->SetOnlineWallpaper(
@@ -5101,7 +5256,7 @@
   variants.emplace_back(kAssetId4, GURL(kDummyUrl4),
                         backdrop::Image::IMAGE_TYPE_LATE_AFTERNOON_MODE);
   const OnlineWallpaperParams& params = OnlineWallpaperParams(
-      kAccountId1, TestWallpaperControllerClient::kDummyCollectionId,
+      kAccountId1, wallpaper_constants::kTimeOfDayWallpaperCollectionId,
       WALLPAPER_LAYOUT_CENTER_CROPPED,
       /*preview_mode=*/false, /*from_user=*/true,
       /*daily_refresh_enabled=*/false, kUnitId, variants);
diff --git a/ash/wallpaper/wallpaper_pref_manager.cc b/ash/wallpaper/wallpaper_pref_manager.cc
index c2a053c..a160c82b 100644
--- a/ash/wallpaper/wallpaper_pref_manager.cc
+++ b/ash/wallpaper/wallpaper_pref_manager.cc
@@ -651,7 +651,7 @@
 
 // static
 bool WallpaperPrefManager::ShouldSyncOut(const WallpaperInfo& local_info) {
-  if (IsTimeOfDayWallpaper(local_info)) {
+  if (IsTimeOfDayWallpaper(local_info.collection_id)) {
     // Time Of Day wallpapers are not syncable.
     return false;
   }
@@ -679,7 +679,7 @@
   if (synced_info.date < local_info.date) {
     return false;
   }
-  if (IsTimeOfDayWallpaper(local_info)) {
+  if (IsTimeOfDayWallpaper(local_info.collection_id)) {
     // Time Of Day wallpapers cannot be overwritten by other wallpapers.
     return false;
   }
diff --git a/ash/wallpaper/wallpaper_pref_manager_unittest.cc b/ash/wallpaper/wallpaper_pref_manager_unittest.cc
index 3265ea2..bbf0fdd 100644
--- a/ash/wallpaper/wallpaper_pref_manager_unittest.cc
+++ b/ash/wallpaper/wallpaper_pref_manager_unittest.cc
@@ -13,6 +13,7 @@
 #include "ash/session/test_pref_service_provider.h"
 #include "ash/session/test_session_controller_client.h"
 #include "ash/wallpaper/test_wallpaper_controller_client.h"
+#include "ash/wallpaper/wallpaper_constants.h"
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
 #include "base/run_loop.h"
@@ -518,6 +519,7 @@
                         backdrop::Image::IMAGE_TYPE_LATE_AFTERNOON_MODE);
   WallpaperInfo info = InfoWithType(WallpaperType::kOnline);
   info.variants = variants;
+  info.collection_id = wallpaper_constants::kTimeOfDayWallpaperCollectionId;
   EXPECT_FALSE(WallpaperPrefManager::ShouldSyncOut(info));
 }
 
@@ -537,6 +539,8 @@
   variants.emplace_back(kAssetId4, GURL(kDummyUrl4),
                         backdrop::Image::IMAGE_TYPE_LATE_AFTERNOON_MODE);
   local_info.variants = variants;
+  local_info.collection_id =
+      wallpaper_constants::kTimeOfDayWallpaperCollectionId;
   EXPECT_FALSE(WallpaperPrefManager::ShouldSyncIn(synced_info, local_info,
                                                   /*is_oobe=*/false));
   EXPECT_TRUE(WallpaperPrefManager::ShouldSyncIn(synced_info, local_info,
diff --git a/ash/wallpaper/wallpaper_time_of_day_scheduler.cc b/ash/wallpaper/wallpaper_time_of_day_scheduler.cc
new file mode 100644
index 0000000..4a138fe
--- /dev/null
+++ b/ash/wallpaper/wallpaper_time_of_day_scheduler.cc
@@ -0,0 +1,31 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/wallpaper/wallpaper_time_of_day_scheduler.h"
+
+#include "ash/constants/ash_pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+
+namespace ash {
+
+WallpaperTimeOfDayScheduler::WallpaperTimeOfDayScheduler()
+    : ScheduledFeature(prefs::kWallpaperTimeOfDayStatus,
+                       prefs::kWallpaperTimeOfDayScheduleType,
+                       "",
+                       "") {}
+
+// static
+void WallpaperTimeOfDayScheduler::RegisterProfilePrefs(
+    PrefRegistrySimple* registry) {
+  registry->RegisterBooleanPref(prefs::kWallpaperTimeOfDayStatus, false);
+  registry->RegisterIntegerPref(
+      prefs::kWallpaperTimeOfDayScheduleType,
+      static_cast<int>(ScheduleType::kSunsetToSunrise));
+}
+
+const char* WallpaperTimeOfDayScheduler::GetFeatureName() const {
+  return "WallpaperTimeOfDayScheduler";
+}
+
+}  // namespace ash
diff --git a/ash/wallpaper/wallpaper_time_of_day_scheduler.h b/ash/wallpaper/wallpaper_time_of_day_scheduler.h
new file mode 100644
index 0000000..49af24a
--- /dev/null
+++ b/ash/wallpaper/wallpaper_time_of_day_scheduler.h
@@ -0,0 +1,36 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_WALLPAPER_WALLPAPER_TIME_OF_DAY_SCHEDULER_H_
+#define ASH_WALLPAPER_WALLPAPER_TIME_OF_DAY_SCHEDULER_H_
+
+#include "ash/system/scheduled_feature/scheduled_feature.h"
+
+class PrefRegistrySimple;
+
+namespace ash {
+
+// Only applies to the time-of-day wallpaper collection. This is always stuck
+// on the `kSunsetToSunrise` schedule and dictates when the time-of-day
+// wallpaper changes. All other wallpaper collections follow D/L mode's
+// schedule settings.
+class WallpaperTimeOfDayScheduler : public ScheduledFeature {
+ public:
+  WallpaperTimeOfDayScheduler();
+  WallpaperTimeOfDayScheduler(const WallpaperTimeOfDayScheduler& other) =
+      delete;
+  WallpaperTimeOfDayScheduler& operator=(
+      const WallpaperTimeOfDayScheduler& rhs) = delete;
+  ~WallpaperTimeOfDayScheduler() override = default;
+
+  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
+ private:
+  // ScheduledFeature:
+  const char* GetFeatureName() const override;
+};
+
+}  // namespace ash
+
+#endif  // ASH_WALLPAPER_WALLPAPER_DAILY_REFRESH_SCHEDULER_H_
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_online_variant_utils.cc b/ash/wallpaper/wallpaper_utils/wallpaper_online_variant_utils.cc
index 26b69d1c..224f47f 100644
--- a/ash/wallpaper/wallpaper_utils/wallpaper_online_variant_utils.cc
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_online_variant_utils.cc
@@ -5,6 +5,7 @@
 #include "ash/wallpaper/wallpaper_utils/wallpaper_online_variant_utils.h"
 
 #include "ash/public/cpp/wallpaper/online_wallpaper_variant.h"
+#include "ash/wallpaper/wallpaper_constants.h"
 #include "base/ranges/algorithm.h"
 
 namespace ash {
@@ -77,15 +78,8 @@
   return nullptr;
 }
 
-bool IsTimeOfDayWallpaper(const WallpaperInfo& wallpaper_info) {
-  const std::vector<OnlineWallpaperVariant>& variants = wallpaper_info.variants;
-  return base::ranges::any_of(
-      variants, [](const OnlineWallpaperVariant& variant) {
-        return variant.type ==
-                   backdrop::Image_ImageType_IMAGE_TYPE_MORNING_MODE ||
-               variant.type ==
-                   backdrop::Image_ImageType_IMAGE_TYPE_LATE_AFTERNOON_MODE;
-      });
+bool IsTimeOfDayWallpaper(const std::string& collection_id) {
+  return collection_id == wallpaper_constants::kTimeOfDayWallpaperCollectionId;
 }
 
 }  // namespace ash
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_online_variant_utils.h b/ash/wallpaper/wallpaper_utils/wallpaper_online_variant_utils.h
index d5f6010..fc6e1c5 100644
--- a/ash/wallpaper/wallpaper_utils/wallpaper_online_variant_utils.h
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_online_variant_utils.h
@@ -24,9 +24,9 @@
     const std::vector<OnlineWallpaperVariant>& variants,
     ScheduleCheckpoint checkpoint);
 
-// Returns whether the given |wallpaper_info| stores the info of a Time of Day
-// wallpaper.
-ASH_EXPORT bool IsTimeOfDayWallpaper(const WallpaperInfo& wallpaper_info);
+// Returns whether the given |collection_id| matches the Time of Day wallpaper
+// collection.
+ASH_EXPORT bool IsTimeOfDayWallpaper(const std::string& collection_id);
 
 }  // namespace ash
 
diff --git a/ash/webui/eche_app_ui/resources/browser_proxy.js b/ash/webui/eche_app_ui/resources/browser_proxy.js
index 3c84fb70..160007d 100644
--- a/ash/webui/eche_app_ui/resources/browser_proxy.js
+++ b/ash/webui/eche_app_ui/resources/browser_proxy.js
@@ -120,7 +120,7 @@
 // window.close() doesn't work from the iframe.
 guestMessagePipe.registerHandler(Message.CLOSE_WINDOW, async () => {
   const info = /** @type {!SystemInfo} */ (await systemInfo.getSystemInfo());
-  const systemInfoJson = JSON.parse(JSON.stringify(info));
+  const systemInfoJson = structuredClone(info);
   console.log('echeapi browser_proxy.js window.close');
   displayStreamHandler.onStreamStatusChanged(
       ash.echeApp.mojom.StreamStatus.kStreamStatusStopped);
@@ -140,7 +140,7 @@
 
 guestMessagePipe.registerHandler(Message.IS_ACCESSIBILITY_ENABLED, async () => {
   const result = await accessibility.isAccessibilityEnabled();
-  return result.enabled;
+  return {result: result.enabled};
 });
 
 // Add Screen Backlight state listener and send state via pipes.
@@ -174,13 +174,13 @@
     (enabled) => {
       console.log('echeapi browser_proxy.js enableAccessibilityTreeStreaming');
       guestMessagePipe.sendMessage(
-          Message.ACCESSIBILITY_SET_TREE_STREAMING_ENABLED, enabled);
+          Message.ACCESSIBILITY_SET_TREE_STREAMING_ENABLED, {enabled});
     });
 
 accessibilityObserverRouter.enableExploreByTouch.addListener((enabled) => {
   console.log('echeapi browser_proxy.js enableExploreByTouch');
   guestMessagePipe.sendMessage(
-      Message.ACCESSIBILITY_SET_EXPLORE_BY_TOUCH_ENABLED, enabled);
+      Message.ACCESSIBILITY_SET_EXPLORE_BY_TOUCH_ENABLED, {enabled});
 });
 
 accessibilityObserverRouter.performAction.addListener((action) => {
diff --git a/ash/webui/eche_app_ui/resources/receiver.js b/ash/webui/eche_app_ui/resources/receiver.js
index 9ee36db..5575f15 100644
--- a/ash/webui/eche_app_ui/resources/receiver.js
+++ b/ash/webui/eche_app_ui/resources/receiver.js
@@ -84,17 +84,17 @@
 
 let setAccessibilityEnabledCallback = null;
 parentMessagePipe.registerHandler(
-    Message.ACCESSIBILITY_SET_TREE_STREAMING_ENABLED, (enabled) => {
+    Message.ACCESSIBILITY_SET_TREE_STREAMING_ENABLED, (payload) => {
       if (setAccessibilityEnabledCallback) {
-        setAccessibilityEnabledCallback(enabled);
+        setAccessibilityEnabledCallback(payload.enabled);
       }
     });
 
 let setExploreByTouchEnabledCallback = null;
 parentMessagePipe.registerHandler(
-    Message.ACCESSIBILITY_SET_EXPLORE_BY_TOUCH_ENABLED, (enabled) => {
+    Message.ACCESSIBILITY_SET_EXPLORE_BY_TOUCH_ENABLED, (payload) => {
       if (setExploreByTouchEnabledCallback) {
-        setExploreByTouchEnabledCallback(enabled);
+        setExploreByTouchEnabledCallback(payload.enabled);
       }
     });
 
@@ -152,7 +152,12 @@
 
   isAccessibilityEnabled() {
     console.log('echeapi receiver.js isAccessibilityEnabled');
-    return (parentMessagePipe.sendMessage(Message.IS_ACCESSIBILITY_ENABLED));
+    return new Promise((resolve, reject) => {
+      parentMessagePipe.sendMessage(Message.IS_ACCESSIBILITY_ENABLED)
+          .then(payload => {
+            resolve(payload.result);
+          }, reject);
+    });
   }
 
   onScreenBacklightStateChanged(callback) {
diff --git a/ash/webui/settings/public/constants/setting.mojom b/ash/webui/settings/public/constants/setting.mojom
index da4aac9..9557451 100644
--- a/ash/webui/settings/public/constants/setting.mojom
+++ b/ash/webui/settings/public/constants/setting.mojom
@@ -41,6 +41,7 @@
   kWifiHidden = 29,
   kHotspotOnOff = 30,
   kHotspotAutoDisabled = 31,
+  kCellularAddApn = 32,
 
   // Bluetooth section.
   kBluetoothOnOff = 100,
diff --git a/ash/wm/multitask_menu_nudge_controller_unittest.cc b/ash/wm/multitask_menu_nudge_controller_unittest.cc
index 560b7c3..0964173 100644
--- a/ash/wm/multitask_menu_nudge_controller_unittest.cc
+++ b/ash/wm/multitask_menu_nudge_controller_unittest.cc
@@ -11,6 +11,7 @@
 #include "ash/frame/non_client_frame_view_ash.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
+#include "ash/test/ash_test_util.h"
 #include "ash/wm/desks/desk.h"
 #include "ash/wm/desks/desks_test_util.h"
 #include "ash/wm/multitask_menu_nudge_delegate_ash.h"
@@ -24,8 +25,6 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/simple_test_clock.h"
 #include "chromeos/ui/base/nudge_util.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
-#include "chromeos/ui/frame/caption_buttons/frame_size_button.h"
 #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller.h"
 #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller_test_api.h"
 #include "chromeos/ui/frame/multitask_menu/multitask_button.h"
@@ -34,7 +33,6 @@
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/size.h"
-#include "ui/views/widget/any_widget_observer.h"
 #include "ui/wm/core/window_util.h"
 
 namespace ash {
@@ -162,20 +160,8 @@
   // accelerator does not cause the crash mentioned in the bug because the
   // presence of the multitask menu causes an activation change which leads to
   // restacking that does not happen otherwise.
-  views::NamedWidgetShownWaiter waiter(
-      views::test::AnyWidgetTestPasskey{},
-      std::string("MultitaskMenuBubbleWidget"));
-  auto* size_button = static_cast<chromeos::FrameSizeButton*>(
-      NonClientFrameViewAsh::Get(window.get())
-          ->GetHeaderView()
-          ->caption_button_container()
-          ->size_button());
-  size_button->ShowMultitaskMenu(
-      chromeos::MultitaskMenuEntryType::kFrameSizeButtonHover);
-  views::WidgetDelegate* delegate =
-      waiter.WaitIfNeededAndGet()->widget_delegate();
-  auto* multitask_menu =
-      static_cast<chromeos::MultitaskMenu*>(delegate->AsDialogDelegate());
+  chromeos::MultitaskMenu* multitask_menu =
+      ShowAndWaitMultitaskMenuForWindow(window.get());
 
   // After floating the window from the multitask menu, there is no crash.
   LeftClickOn(
@@ -415,17 +401,7 @@
   ASSERT_TRUE(GetNudgeWidgetForWindow(window.get()));
 
   // When opening the multitask menu, the nudge should dismiss immediately.
-  views::NamedWidgetShownWaiter waiter(
-      views::test::AnyWidgetTestPasskey{},
-      std::string("MultitaskMenuBubbleWidget"));
-  auto* size_button = static_cast<chromeos::FrameSizeButton*>(
-      NonClientFrameViewAsh::Get(window.get())
-          ->GetHeaderView()
-          ->caption_button_container()
-          ->size_button());
-  size_button->ShowMultitaskMenu(
-      chromeos::MultitaskMenuEntryType::kFrameSizeButtonHover);
-  waiter.WaitIfNeededAndGet();
+  std::ignore = ShowAndWaitMultitaskMenuForWindow(window.get());
   EXPECT_FALSE(GetNudgeWidgetForWindow(window.get()));
 
   // Advance the clock and then destroy the window and create a new window.
diff --git a/ash/wm/resize_shadow_and_cursor_unittest.cc b/ash/wm/resize_shadow_and_cursor_unittest.cc
index 86c6118..57977f4 100644
--- a/ash/wm/resize_shadow_and_cursor_unittest.cc
+++ b/ash/wm/resize_shadow_and_cursor_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 "ash/frame/non_client_frame_view_ash.h"
 #include "ash/public/cpp/test/shell_test_api.h"
 #include "ash/public/cpp/window_properties.h"
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
+#include "ash/test/ash_test_util.h"
 #include "ash/test/test_window_builder.h"
 #include "ash/wm/desks/desks_util.h"
 #include "ash/wm/resize_shadow.h"
@@ -18,10 +18,8 @@
 #include "base/memory/raw_ptr.h"
 #include "base/ranges/algorithm.h"
 #include "chromeos/ui/base/chromeos_ui_constants.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
-#include "chromeos/ui/frame/caption_buttons/frame_size_button.h"
 #include "chromeos/ui/frame/multitask_menu/multitask_button.h"
-#include "chromeos/ui/frame/multitask_menu/multitask_menu_metrics.h"
+#include "chromeos/ui/frame/multitask_menu/multitask_menu.h"
 #include "chromeos/ui/frame/multitask_menu/multitask_menu_view_test_api.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -598,27 +596,15 @@
   EXPECT_TRUE(resize_shadow);
 
   // Open multi-task menu by hovering on the resize button.
-  // TODO(b/300668220): Extract this block into a helper.
-  views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
-                                       "MultitaskMenuBubbleWidget");
-  chromeos::FrameCaptionButtonContainerView::TestApi test_api(
-      NonClientFrameViewAsh::Get(test_window.get())
-          ->GetHeaderView()
-          ->caption_button_container());
-  auto* size_button =
-      static_cast<chromeos::FrameSizeButton*>(test_api.size_button());
-  size_button->ShowMultitaskMenu(
-      chromeos::MultitaskMenuEntryType::kFrameSizeButtonHover);
-  waiter.WaitIfNeededAndGet();
+  chromeos::MultitaskMenu* multitask_menu =
+      ShowAndWaitMultitaskMenuForWindow(test_window.get());
+  ASSERT_TRUE(multitask_menu);
 
   // Click on the floating window option.
   ui::ScopedAnimationDurationScaleMode zero_duration_mode(
       ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
-  auto* menu_view = static_cast<chromeos::MultitaskMenu*>(
-                        size_button->multitask_menu_widget_for_testing()
-                            ->widget_delegate()
-                            ->AsDialogDelegate())
-                        ->multitask_menu_view();
+  chromeos::MultitaskMenuView* menu_view =
+      multitask_menu->multitask_menu_view();
   LeftClickOn(chromeos::MultitaskMenuViewTestApi(menu_view).GetFloatButton());
   EXPECT_TRUE(WindowState::Get(test_window.get())->IsFloated());
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 5bb39e9..8bd239100 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -24,7 +24,7 @@
 import("//build/buildflag_header.gni")
 import("//build/config/arm.gni")
 import("//build/config/c++/c++.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/compiler/compiler.gni")
 import("//build/config/cronet/config.gni")
diff --git a/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn b/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn
index b5555fbd..8202608 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn
+++ b/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn
@@ -4,7 +4,7 @@
 
 import("//build/buildflag_header.gni")
 import("//build/config/android/config.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/compiler/compiler.gni")
 import("//build/config/dcheck_always_on.gni")
diff --git a/base/android/java/src/org/chromium/base/MathUtils.java b/base/android/java/src/org/chromium/base/MathUtils.java
index aa55886..589a17e3 100644
--- a/base/android/java/src/org/chromium/base/MathUtils.java
+++ b/base/android/java/src/org/chromium/base/MathUtils.java
@@ -151,15 +151,6 @@
     }
 
     /**
-     * Compares two long values. Same as {@link Long#compare}, but available on all API levels.
-     *
-     * TODO(newt): replace this with Long.compare() once Chrome only supports API level 19+.
-     */
-    public static int compareLongs(long lhs, long rhs) {
-        return lhs < rhs ? -1 : (lhs == rhs ? 0 : 1);
-    }
-
-    /**
      * Determine if two floats are equal.
      * @param f1 The first float to compare.
      * @param f2 The second float to compare.
diff --git a/base/enterprise_util_mac.mm b/base/enterprise_util_mac.mm
index 1977180..2bad2ed 100644
--- a/base/enterprise_util_mac.mm
+++ b/base/enterprise_util_mac.mm
@@ -112,7 +112,8 @@
 
 DeviceUserDomainJoinState AreDeviceAndUserJoinedToDomain() {
   static DeviceUserDomainJoinState state = [] {
-    DeviceUserDomainJoinState state{false, false};
+    DeviceUserDomainJoinState state{.device_joined = false,
+                                    .user_joined = false};
 
     @autoreleasepool {
       ODSession* session = [ODSession defaultSession];
@@ -121,27 +122,23 @@
         return state;
       }
 
+      // Machines that are domain-joined have nodes under "/LDAPv3" or "/Active
+      // Directory". See https://stackoverflow.com/questions/32470557/ and
+      // https://stackoverflow.com/questions/69093499/, respectively, for
+      // examples.
       NSError* error = nil;
-
-      NSArray<NSString*>* all_node_names =
-          [session nodeNamesAndReturnError:&error];
-      if (!all_node_names) {
+      NSArray<NSString*>* node_names = [session nodeNamesAndReturnError:&error];
+      if (!node_names) {
         DLOG(WARNING) << "ODSession failed to give node names: "
                       << error.localizedDescription.UTF8String;
         return state;
       }
 
-      NSUInteger num_nodes = all_node_names.count;
-      if (num_nodes < 3) {
-        DLOG(WARNING) << "ODSession returned too few node names: "
-                      << all_node_names.description.UTF8String;
-        return state;
-      }
-
-      if (num_nodes > 3) {
-        // Non-enterprise machines have:"/Search", "/Search/Contacts",
-        // "/Local/Default". Everything else would be enterprise management.
-        state.device_joined = true;
+      for (NSString* node_name in node_names) {
+        if ([node_name hasPrefix:@"/LDAPv3"] ||
+            [node_name hasPrefix:@"/Active Directory"]) {
+          state.device_joined = true;
+        }
       }
 
       ODNode* node = [ODNode nodeWithSession:session
diff --git a/base/files/file_path_watcher_inotify.cc b/base/files/file_path_watcher_inotify.cc
index e37eaa7..2fe86b4 100644
--- a/base/files/file_path_watcher_inotify.cc
+++ b/base/files/file_path_watcher_inotify.cc
@@ -761,12 +761,22 @@
        current = enumerator.Next()) {
     DCHECK(enumerator.GetInfo().IsDirectory());
 
+    // Check `recursive_watches_by_path_` as a heuristic to determine if this
+    // needs to be an add or update operation.
     if (!Contains(recursive_watches_by_path_, current)) {
-      // Add new watches.
+      // Try to add new watches.
       InotifyReader::Watch watch =
           g_inotify_reader.Get().AddWatch(current, this);
       if (watch == InotifyReader::kWatchLimitExceeded)
         return false;
+
+      // The `watch` returned by inotify already exists. This is actually an
+      // update operation.
+      auto it = recursive_paths_by_watch_.find(watch);
+      if (it != recursive_paths_by_watch_.end()) {
+        recursive_watches_by_path_.erase(it->second);
+        recursive_paths_by_watch_.erase(it);
+      }
       TrackWatchForRecursion(watch, current);
     } else {
       // Update existing watches.
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc
index 841d8e61..4ecc604 100644
--- a/base/task/sequence_manager/task_queue_impl.cc
+++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -41,26 +41,10 @@
 namespace base {
 namespace sequence_manager {
 
-namespace {
-
-// Controls whether cancelled tasks are removed from the delayed queue.
-BASE_FEATURE(kSweepCancelledTasks,
-             "SweepCancelledTasks",
-             FEATURE_ENABLED_BY_DEFAULT);
-
-}  // namespace
-
 namespace internal {
 
 namespace {
 
-// Cache of the state of the kRemoveCanceledTasksInTaskQueue,
-// kSweepCancelledTasks and kExplicitHighResolutionTimerWin features. This
-// avoids the need to constantly query their enabled state through
-// FeatureList::IsEnabled().
-bool g_is_remove_canceled_tasks_in_task_queue_enabled = true;
-bool g_is_sweep_cancelled_tasks_enabled =
-    kSweepCancelledTasks.default_state == FEATURE_ENABLED_BY_DEFAULT;
 // An atomic is used here because the value is queried from other threads when
 // tasks are posted cross-thread, which can race with its initialization.
 std::atomic<base::TimeDelta> g_max_precise_delay{kDefaultMaxPreciseDelay};
@@ -144,12 +128,6 @@
     OnceClosure callback,
     TimeTicks delayed_run_time,
     base::subtle::DelayPolicy delay_policy) {
-  if (!g_is_remove_canceled_tasks_in_task_queue_enabled) {
-    // This will revert to PostDelayedTaskAt() with default DelayedTaskHandle.
-    return SequencedTaskRunner::PostCancelableDelayedTaskAt(
-        pass_key, location, std::move(callback), delayed_run_time,
-        delay_policy);
-  }
   return task_poster_->PostCancelableTask(
       PostedTask(this, std::move(callback), location, delayed_run_time,
                  delay_policy, Nestable::kNestable, task_type_));
@@ -160,11 +138,6 @@
     const Location& location,
     OnceClosure callback,
     TimeDelta delay) {
-  if (!g_is_remove_canceled_tasks_in_task_queue_enabled) {
-    return SequencedTaskRunner::PostCancelableDelayedTask(
-        pass_key, location, std::move(callback), delay);
-  }
-
   return task_poster_->PostCancelableTask(
       PostedTask(this, std::move(callback), location, delay,
                  Nestable::kNestable, task_type_));
@@ -185,9 +158,6 @@
 
 // static
 void TaskQueueImpl::InitializeFeatures() {
-  ApplyRemoveCanceledTasksInTaskQueue();
-  g_is_sweep_cancelled_tasks_enabled =
-      FeatureList::IsEnabled(kSweepCancelledTasks);
   g_max_precise_delay = kMaxPreciseDelay.Get();
 #if BUILDFLAG(IS_WIN)
   g_explicit_high_resolution_timer_win.store(
@@ -196,27 +166,6 @@
 #endif  // BUILDFLAG(IS_WIN)
 }
 
-// static
-void TaskQueueImpl::ApplyRemoveCanceledTasksInTaskQueue() {
-  // Since kRemoveCanceledTasksInTaskQueue is not constexpr (forbidden for
-  // Features), it cannot be used to initialize
-  // |g_is_remove_canceled_tasks_in_task_queue_enabled| at compile time. At
-  // least DCHECK that its initial value matches the default value of the
-  // feature here.
-  DCHECK_EQ(g_is_remove_canceled_tasks_in_task_queue_enabled,
-            kRemoveCanceledTasksInTaskQueue.default_state ==
-                FEATURE_ENABLED_BY_DEFAULT);
-  g_is_remove_canceled_tasks_in_task_queue_enabled =
-      FeatureList::IsEnabled(kRemoveCanceledTasksInTaskQueue);
-}
-
-// static
-void TaskQueueImpl::ResetRemoveCanceledTasksInTaskQueueForTesting() {
-  g_is_remove_canceled_tasks_in_task_queue_enabled =
-      kRemoveCanceledTasksInTaskQueue.default_state ==
-      FEATURE_ENABLED_BY_DEFAULT;
-}
-
 TaskQueueImpl::TaskQueueImpl(SequenceManagerImpl* sequence_manager,
                              WakeUpQueue* wake_up_queue,
                              const TaskQueue::Spec& spec)
@@ -1199,20 +1148,19 @@
   if (main_thread_only().delayed_incoming_queue.empty())
     return;
 
-  if (g_is_sweep_cancelled_tasks_enabled) {
-    main_thread_only().delayed_incoming_queue.SweepCancelledTasks(
-        sequence_manager_);
+  main_thread_only().delayed_incoming_queue.SweepCancelledTasks(
+      sequence_manager_);
 
-    // If deleting one of the cancelled tasks shut down this queue, bail out.
-    // Note that in this scenario |this| is still valid, but some fields of the
-    // queue have been cleared out by |UnregisterTaskQueue|.
-    if (!main_thread_only().delayed_work_queue)
-      return;
-
-    LazyNow lazy_now(now);
-    UpdateWakeUp(&lazy_now);
+  // If deleting one of the cancelled tasks shut down this queue, bail out.
+  // Note that in this scenario |this| is still valid, but some fields of the
+  // queue have been cleared out by |UnregisterTaskQueue|.
+  if (!main_thread_only().delayed_work_queue) {
+    return;
   }
 
+  LazyNow lazy_now(now);
+  UpdateWakeUp(&lazy_now);
+
   // Also consider shrinking the work queue if it's wasting memory.
   main_thread_only().delayed_work_queue->MaybeShrinkQueue();
   main_thread_only().immediate_work_queue->MaybeShrinkQueue();
diff --git a/base/task/sequence_manager/task_queue_impl.h b/base/task/sequence_manager/task_queue_impl.h
index 6544d53..ad91189 100644
--- a/base/task/sequence_manager/task_queue_impl.h
+++ b/base/task/sequence_manager/task_queue_impl.h
@@ -80,15 +80,6 @@
   // after FeatureList initialization and while Chrome is still single-threaded.
   static void InitializeFeatures();
 
-  // Sets the global cached state of the RemoveCanceledTasksInTaskQueue feature
-  // according to its enabled state. Must be invoked after FeatureList
-  // initialization.
-  static void ApplyRemoveCanceledTasksInTaskQueue();
-
-  // Resets the global cached state of the RemoveCanceledTasksInTaskQueue
-  // feature according to its default state.
-  static void ResetRemoveCanceledTasksInTaskQueueForTesting();
-
   TaskQueueImpl(SequenceManagerImpl* sequence_manager,
                 WakeUpQueue* wake_up_queue,
                 const TaskQueue::Spec& spec);
diff --git a/base/task/sequence_manager/task_queue_unittest.cc b/base/task/sequence_manager/task_queue_unittest.cc
index 3fff0974..8d34fd7 100644
--- a/base/task/sequence_manager/task_queue_unittest.cc
+++ b/base/task/sequence_manager/task_queue_unittest.cc
@@ -103,67 +103,43 @@
   voter.reset();
 }
 
-class ScopedNoWakeUpsForCanceledTasks {
- public:
-  explicit ScopedNoWakeUpsForCanceledTasks(bool feature_enabled) {
-    scoped_feature_list_.InitWithFeatureState(kRemoveCanceledTasksInTaskQueue,
-                                              feature_enabled);
-    TaskQueueImpl::ApplyRemoveCanceledTasksInTaskQueue();
-  }
+TEST(TaskQueueTest, CanceledTaskRemoved) {
+  auto sequence_manager = CreateSequenceManagerOnCurrentThreadWithPump(
+      MessagePump::Create(MessagePumpType::DEFAULT));
+  auto queue =
+      sequence_manager->CreateTaskQueue(TaskQueue::Spec(QueueName::TEST_TQ));
 
-  ~ScopedNoWakeUpsForCanceledTasks() {
-    TaskQueueImpl::ResetRemoveCanceledTasksInTaskQueueForTesting();
-  }
+  // Get the default task runner.
+  auto task_runner = queue->task_runner();
+  EXPECT_EQ(queue->GetNumberOfPendingTasks(), 0u);
 
- private:
-  test::ScopedFeatureList scoped_feature_list_;
-};
+  bool task_ran = false;
+  DelayedTaskHandle delayed_task_handle =
+      task_runner->PostCancelableDelayedTask(
+          subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
+          BindLambdaForTesting([&task_ran]() { task_ran = true; }),
+          Seconds(20));
+  EXPECT_EQ(queue->GetNumberOfPendingTasks(), 1u);
 
-TEST(TaskQueueTest, CanceledTaskRemovedIfFeatureEnabled) {
-  for (bool feature_enabled : {false, true}) {
-    ScopedNoWakeUpsForCanceledTasks scoped_no_wake_ups_for_canceled_tasks(
-        feature_enabled);
+  // The task is only removed from the queue if the feature is enabled.
+  delayed_task_handle.CancelTask();
+  EXPECT_EQ(queue->GetNumberOfPendingTasks(), 0u);
 
-    auto sequence_manager = CreateSequenceManagerOnCurrentThreadWithPump(
-        MessagePump::Create(MessagePumpType::DEFAULT));
-    auto queue =
-        sequence_manager->CreateTaskQueue(TaskQueue::Spec(QueueName::TEST_TQ));
-
-    // Get the default task runner.
-    auto task_runner = queue->task_runner();
-    EXPECT_EQ(queue->GetNumberOfPendingTasks(), 0u);
-
-    bool task_ran = false;
-    DelayedTaskHandle delayed_task_handle =
-        task_runner->PostCancelableDelayedTask(
-            subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
-            BindLambdaForTesting([&task_ran]() { task_ran = true; }),
-            Seconds(20));
-    EXPECT_EQ(queue->GetNumberOfPendingTasks(), 1u);
-
-    // The task is only removed from the queue if the feature is enabled.
-    delayed_task_handle.CancelTask();
-    EXPECT_EQ(queue->GetNumberOfPendingTasks(), feature_enabled ? 0u : 1u);
-
-    // In any case, the task never actually ran.
-    EXPECT_FALSE(task_ran);
-  }
+  // In any case, the task never actually ran.
+  EXPECT_FALSE(task_ran);
 }
 
-// Tests that a task posted through `PostCancelableDelayedTask()`, while the
-// RemoveCanceledDelayedTasksInTaskQueue feature is enabled, is not considered
-// canceled once it has reached the |delayed_work_queue| and is therefore
-// not removed.
+// Tests that a task posted through `PostCancelableDelayedTask()` is not
+// considered canceled once it has reached the |delayed_work_queue| and is
+// therefore not removed.
 //
-// This is a regression test for a bug in `Task::IsCanceled()`
-// (see https://crbug.com/1288882). Note that this function is only called on
-// tasks inside the |delayed_work_queue|, and not for tasks in the
+// This is a regression test for a bug in `Task::IsCanceled()` (see
+// https://crbug.com/1288882). Note that this function is only called on tasks
+// inside the |delayed_work_queue|, and not for tasks in the
 // |delayed_incoming_queue|. This is because a task posted through
 // `PostCancelableDelayedTask()` is always valid while it is in the
 // |delayed_incoming_queue|, since canceling it would remove it from the queue.
 TEST(TaskQueueTest, ValidCancelableTaskIsNotCanceled) {
-  ScopedNoWakeUpsForCanceledTasks scoped_no_wake_ups_for_canceled_tasks(true);
-
   auto sequence_manager = CreateSequenceManagerOnCurrentThreadWithPump(
       MessagePump::Create(MessagePumpType::DEFAULT));
   auto queue =
diff --git a/base/tracing/stdlib/chrome/BUILD.gn b/base/tracing/stdlib/chrome/BUILD.gn
index 7e54d5b..adbd429 100644
--- a/base/tracing/stdlib/chrome/BUILD.gn
+++ b/base/tracing/stdlib/chrome/BUILD.gn
@@ -10,6 +10,5 @@
 # work in the Perfetto repository but does not make sense here.
 import("../../../../../gn/perfetto_sql.gni")
 perfetto_sql_source_set("chrome_sql") {
-  deps = [ "scroll_jank" ]
   sources = chrome_stdlib_sql_files
 }
diff --git a/base/tracing/stdlib/chrome/chrome_scrolls.sql b/base/tracing/stdlib/chrome/chrome_scrolls.sql
index b40aed3..85c1ddc 100644
--- a/base/tracing/stdlib/chrome/chrome_scrolls.sql
+++ b/base/tracing/stdlib/chrome/chrome_scrolls.sql
@@ -5,16 +5,6 @@
 -- Defines slices for all of the individual scrolls in a trace based on the
 -- LatencyInfo-based scroll definition.
 --
--- @column id                          The unique identifier of the scroll.
--- @column ts                          The start timestamp of the scroll.
--- @column dur                         The duration of the scroll.
--- @column gesture_scroll_begin_ts     The earliest timestamp of the
---                                     InputLatency::GestureScrollBegin for the
---                                     corresponding scroll id.
--- @column gesture_scroll_end_ts       The earliest timestamp of the
---                                     InputLatency::GestureScrollEnd for the
---                                     corresponding scroll id.
---
 -- NOTE: this view of top level scrolls is based on the LatencyInfo definition
 -- of a scroll, which differs subtly from the definition based on
 -- EventLatencies.
@@ -22,7 +12,20 @@
 -- WebView instances. Currently gesture_scroll_id unique within an instance, but
 -- is not unique across multiple instances. Switching to an EventLatency based
 -- definition of scrolls should resolve this.
-CREATE PERFETTO TABLE chrome_scrolls AS
+CREATE PERFETTO TABLE chrome_scrolls(
+  -- The unique identifier of the scroll.
+  id INT,
+  -- The start timestamp of the scroll.
+  ts INT,
+  -- The duration of the scroll.
+  dur INT,
+  -- The earliest timestamp of the InputLatency::GestureScrollBegin for the
+  -- corresponding scroll id.
+  gesture_scroll_begin_ts INT,
+  -- The earliest timestamp of the InputLatency::GestureScrollEnd for the
+  -- corresponding scroll id.
+  gesture_scroll_end_ts INT
+) AS
 WITH all_scrolls AS (
   SELECT
     name,
@@ -65,12 +68,14 @@
 -- definition in chrome_scrolls. Note that scrolls may overlap (particularly in
 -- cases of jank/broken traces, etc); so scrolling intervals are not exactly the
 -- same as individual scrolls.
---
--- @column id            The unique identifier of the scroll interval. This may
---                       span multiple scrolls if they overlap.
--- @column ts            The start timestamp of the scroll interval.
--- @column dur           The duration of the scroll interval.
-CREATE VIEW chrome_scrolling_intervals AS
+CREATE PERFETTO VIEW chrome_scrolling_intervals(
+  -- The unique identifier of the scroll interval. This may span multiple scrolls if they overlap.
+  id INT,
+  -- The start timestamp of the scroll interval.
+  ts INT,
+  -- The duration of the scroll interval.
+  dur INT
+) AS
 WITH all_scrolls AS (
   SELECT
     id AS scroll_id,
diff --git a/base/tracing/stdlib/chrome/cpu_powerups.sql b/base/tracing/stdlib/chrome/cpu_powerups.sql
index f21ad51..7d9f4745 100644
--- a/base/tracing/stdlib/chrome/cpu_powerups.sql
+++ b/base/tracing/stdlib/chrome/cpu_powerups.sql
@@ -18,22 +18,26 @@
 --      slices that ran after a CPU power-up.
 
 -- The CPU power transitions in the trace.
---
--- @column ts            The timestamp at the start of the slice.
--- @column dur           The duration of the slice.
--- @column cpu           The CPU on which the transition occurred
--- @column power_state   The power state that the CPU was in at time 'ts' for
---                       duration 'dur'.
--- @column previous_power_state The power state that the CPU was previously in.
--- @column powerup_id    A unique ID for the CPU power-up.
---
 -- Power states are encoded as non-negative integers, with zero representing
 -- full-power operation and positive values representing increasingly deep
 -- sleep states.
 --
 -- On ARM systems, power state 1 represents the WFI (Wait For Interrupt) sleep
 -- state that the CPU enters while idle.
-CREATE VIEW chrome_cpu_power_slice AS
+CREATE PERFETTO VIEW chrome_cpu_power_slice(
+  -- The timestamp at the start of the slice.
+  ts INT,
+  -- The duration of the slice.
+  dur INT,
+  -- The CPU on which the transition occurred
+  cpu INT,
+  -- The power state that the CPU was in at time 'ts' for duration 'dur'.
+  power_state INT,
+  -- The power state that the CPU was previously in.
+  previous_power_state INT,
+  -- A unique ID for the CPU power-up.
+  powerup_id INT
+) AS
   WITH cpu_power_states AS (
     SELECT
       c.id AS id,
@@ -67,7 +71,7 @@
     ORDER BY ts ASC;
 
 -- We do not want scheduler slices with utid = 0 (the 'swapper' kernel thread).
-CREATE VIEW internal_cpu_power_valid_sched_slice AS
+CREATE PERFETTO VIEW internal_cpu_power_valid_sched_slice AS
   SELECT *
   FROM sched_slice
   WHERE utid != 0;
@@ -93,14 +97,20 @@
 
 -- The Linux scheduler slices that executed immediately after a
 -- CPU power up.
---
--- @column ts          The timestamp at the start of the slice.
--- @column dur         The duration of the slice.
--- @column cpu         The cpu on which the slice executed.
--- @column sched_id    Id for the sched_slice table.
--- @column utid        Unique id for the thread that ran within the slice.
--- @column previous_power_state   The CPU's power state before this slice.
-CREATE PERFETTO TABLE chrome_cpu_power_first_sched_slice_after_powerup AS
+CREATE PERFETTO TABLE chrome_cpu_power_first_sched_slice_after_powerup(
+  -- The timestamp at the start of the slice.
+  ts INT,
+  -- The duration of the slice.
+  dur INT,
+  -- The cpu on which the slice executed.
+  cpu INT,
+  -- Id for the sched_slice table.
+  sched_id INT,
+  -- Unique id for the thread that ran within the slice.
+  utid INT,
+  -- The CPU's power state before this slice.
+  previous_power_state INT
+) AS
   SELECT
     ts,
     dur,
@@ -125,7 +135,7 @@
 --   slice_id  The slice_id for the top-level slice.
 --   ts        Starting timestamp for the slice.
 --   dur       The duration for the slice.
-CREATE VIEW internal_cpu_power_thread_and_toplevel_slice AS
+CREATE PERFETTO VIEW internal_cpu_power_thread_and_toplevel_slice AS
   SELECT
     t.utid AS utid,
     s.id AS slice_id,
@@ -155,10 +165,12 @@
             internal_cpu_power_thread_and_toplevel_slice PARTITIONED utid);
 
 -- The first top-level slice that ran after a CPU power-up.
---
--- @column slice_id              ID of the slice in the slice table.
--- @column previous_power_state  The power state of the CPU prior to power-up.
-CREATE VIEW chrome_cpu_power_first_toplevel_slice_after_powerup AS
+CREATE PERFETTO VIEW chrome_cpu_power_first_toplevel_slice_after_powerup(
+  -- ID of the slice in the slice table.
+  slice_id INT,
+  -- The power state of the CPU prior to power-up.
+  previous_power_state INT
+) AS
   SELECT slice_id, previous_power_state
   FROM chrome_cpu_power_post_powerup_slice
   GROUP BY cpu, powerup_id
diff --git a/base/tracing/stdlib/chrome/histograms.sql b/base/tracing/stdlib/chrome/histograms.sql
index d7ed82f..b7bb525 100644
--- a/base/tracing/stdlib/chrome/histograms.sql
+++ b/base/tracing/stdlib/chrome/histograms.sql
@@ -6,17 +6,26 @@
 
 -- A helper view on top of the histogram events emitted by Chrome.
 -- Requires "disabled-by-default-histogram_samples" Chrome category.
---
--- @column name          The name of the histogram.
--- @column value         The value of the histogram sample.
--- @column ts            Alias of |slice.ts|.
--- @column thread_name   Thread name.
--- @column utid          Utid of the thread.
--- @column tid           Tid of the thread.
--- @column process_name  Process name.
--- @column upid          Upid of the process.
--- @column pid           Pid of the process.
-CREATE VIEW chrome_histograms AS
+CREATE PERFETTO TABLE chrome_histograms(
+  -- The name of the histogram.
+  name STRING,
+  -- The value of the histogram sample.
+  value INT,
+  -- Alias of |slice.ts|.
+  ts INT,
+  -- Thread name.
+  thread_name STRING,
+  -- Utid of the thread.
+  utid INT,
+  -- Tid of the thread.
+  tid INT,
+  -- Process name.
+  process_name STRING,
+  -- Upid of the process.
+  upid INT,
+  -- Pid of the process.
+  pid INT
+) AS
 SELECT
   extract_arg(slice.arg_set_id, "chrome_histogram_sample.name") as name,
   extract_arg(slice.arg_set_id, "chrome_histogram_sample.sample") as value,
diff --git a/base/tracing/stdlib/chrome/interactions.sql b/base/tracing/stdlib/chrome/interactions.sql
new file mode 100644
index 0000000..36566e3
--- /dev/null
+++ b/base/tracing/stdlib/chrome/interactions.sql
@@ -0,0 +1,36 @@
+-- Copyright 2023 The Chromium Authors
+-- Use of this source code is governed by a BSD-style license that can be
+-- found in the LICENSE file.
+
+-- This file specifies common metrics/tables for critical user interactions. It
+-- is expected to be in flux as metrics are added across different CUI types.
+-- Currently we only track Chrome page loads and their associated metrics.
+
+INCLUDE PERFETTO MODULE chrome.page_loads;
+
+-- All critical user interaction events, including type and table with
+-- associated metrics.
+CREATE PERFETTO TABLE chrome_interactions(
+  -- Identifier of the interaction; this is not guaranteed to be unique to the table -
+  -- rather, it is unique within an individual interaction type. Combine with type to get
+  -- a unique identifier in this table.
+  scoped_id INT,
+  -- Type of this interaction, which together with scoped_id uniquely identifies this
+  -- interaction. Also corresponds to a SQL table name containing more details specific
+  -- to this type of interaction.
+  type STRING,
+  -- Interaction name - e.g. 'PageLoad', 'Tap', etc. Interactions will have unique metrics
+  -- stored in other tables.
+  name STRING,
+  -- Timestamp of the CUI event.
+  ts INT,
+  -- Duration of the CUI event.
+  dur INT
+) AS
+SELECT
+  navigation_id AS scoped_id,
+  'chrome_page_loads' AS type,
+  'PageLoad' AS name,
+  navigation_start_ts AS ts,
+  IFNULL(lcp, fcp) AS dur
+FROM chrome_page_loads;
diff --git a/base/tracing/stdlib/chrome/page_loads.sql b/base/tracing/stdlib/chrome/page_loads.sql
new file mode 100644
index 0000000..365e23f
--- /dev/null
+++ b/base/tracing/stdlib/chrome/page_loads.sql
@@ -0,0 +1,107 @@
+-- Copyright 2023 The Chromium Authors
+-- Use of this source code is governed by a BSD-style license that can be
+-- found in the LICENSE file.
+
+-- TODO(b/306300843): The recorded navigation ids are not guaranteed to be
+-- unique within a trace; they are only guaranteed to be unique within a single
+-- chrome instance. Chrome instance id needs to be recorded, and used here in
+-- combination with navigation id to uniquely identify page load metrics.
+
+INCLUDE PERFETTO MODULE common.slices;
+
+CREATE PERFETTO VIEW internal_fcp_metrics AS
+SELECT
+  ts,
+  dur,
+  EXTRACT_ARG(arg_set_id, 'page_load.navigation_id') AS navigation_id,
+  EXTRACT_ARG(arg_set_id, 'page_load.url') AS url,
+  upid AS browser_upid
+FROM process_slice
+WHERE name = 'PageLoadMetrics.NavigationToFirstContentfulPaint';
+
+CREATE PERFETTO FUNCTION internal_page_load_metrics(event_name STRING)
+RETURNS TABLE(
+  ts LONG,
+  dur LONG,
+  navigation_id INT
+) AS
+SELECT
+  ts,
+  dur,
+  EXTRACT_ARG(arg_set_id, 'page_load.navigation_id')
+    AS navigation_id
+FROM slice
+WHERE name = $event_name;
+
+-- Chrome page loads, including associated high-level metrics and properties.
+CREATE PERFETTO TABLE chrome_page_loads(
+  -- ID of the navigation associated with the page load (i.e. the cross-document
+  -- navigation in primary main frame which created this page's main document).
+  -- Also note that navigation_id is specific to a given Chrome browser process,
+  -- and not globally unique.
+  navigation_id INT,
+  -- Timestamp of the start of navigation.
+  navigation_start_ts INT,
+  -- Duration between the navigation start and the first contentful paint event
+  -- (web.dev/fcp).
+  fcp INT,
+  -- Timestamp of the first contentful paint.
+  fcp_ts INT,
+  -- Duration between the navigation start and the largest contentful paint event
+  -- (web.dev/lcp).
+  lcp INT,
+  -- Timestamp of the largest contentful paint.
+  lcp_ts INT,
+  -- Timestamp of the DomContentLoaded event:
+  -- https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event
+  dom_content_loaded_event_ts INT,
+  -- Timestamp of the window load event:
+  -- https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
+  load_event_ts INT,
+  -- Timestamp of the page self-reporting as fully loaded through the
+  -- performance.mark('mark_fully_loaded') API.
+  mark_fully_loaded_ts INT,
+  -- Timestamp of the page self-reporting as fully visible through the
+  -- performance.mark('mark_fully_visible') API.
+  mark_fully_visible_ts INT,
+  -- Timestamp of the page self-reporting as fully interactive through the
+  -- performance.mark('mark_interactive') API.
+  mark_interactive_ts INT,
+  -- URL at the page load event.
+  url STRING,
+  -- The unique process id (upid) of the browser process where the page load occurred.
+  browser_upid INT
+) AS
+SELECT
+  fcp.navigation_id,
+  fcp.ts AS navigation_start_ts,
+  fcp.dur AS fcp,
+  fcp.ts + fcp.dur AS fcp_ts,
+  lcp.dur AS lcp,
+  IFNULL(lcp.dur, 0) + IFNULL(lcp.ts, 0) AS lcp_ts,
+  load_fired.ts AS dom_content_loaded_event_ts,
+  start_load.ts AS load_event_ts,
+  timing_loaded.ts AS mark_fully_loaded_ts,
+  timing_visible.ts AS mark_fully_visible_ts,
+  timing_interactive.ts AS mark_interactive_ts,
+  fcp.url,
+  fcp.browser_upid
+FROM internal_fcp_metrics fcp
+LEFT JOIN
+  internal_page_load_metrics('PageLoadMetrics.NavigationToLargestContentfulPaint') lcp
+    USING (navigation_id)
+LEFT JOIN
+  internal_page_load_metrics('PageLoadMetrics.NavigationToDOMContentLoadedEventFired') load_fired
+    using (navigation_id)
+LEFT JOIN
+  internal_page_load_metrics('PageLoadMetrics.NavigationToMainFrameOnLoad') start_load
+    using (navigation_id)
+LEFT JOIN
+  internal_page_load_metrics('PageLoadMetrics.UserTimingMarkFullyLoaded') timing_loaded
+    using (navigation_id)
+LEFT JOIN
+  internal_page_load_metrics('PageLoadMetrics.UserTimingMarkFullyVisible') timing_visible
+    using (navigation_id)
+LEFT JOIN
+  internal_page_load_metrics('PageLoadMetrics.UserTimingMarkInteractive') timing_interactive
+    using (navigation_id);
diff --git a/base/tracing/stdlib/chrome/perfetto_sql_files.gni b/base/tracing/stdlib/chrome/perfetto_sql_files.gni
index bebd821..23c8329 100644
--- a/base/tracing/stdlib/chrome/perfetto_sql_files.gni
+++ b/base/tracing/stdlib/chrome/perfetto_sql_files.gni
@@ -7,7 +7,9 @@
   "chrome_scrolls.sql",
   "cpu_powerups.sql",
   "histograms.sql",
+  "interactions.sql",
   "metadata.sql",
+  "page_loads.sql",
   "speedometer.sql",
   "tasks.sql",
   "vsync_intervals.sql",
diff --git a/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_intervals.sql b/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_intervals.sql
index 1a44f733..3a8d067c 100644
--- a/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_intervals.sql
+++ b/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_intervals.sql
@@ -8,23 +8,28 @@
 
 -- Selects EventLatency slices that correspond with janks in a scroll. This is
 -- based on the V3 version of scroll jank metrics.
---
--- @column id INT                     The slice id.
--- @column ts INT                     The start timestamp of the slice.
--- @column dur INT                    The duration of the slice.
--- @column track_id INT               The track_id for the slice.
--- @column name STRING                The name of the slice (EventLatency).
--- @column cause_of_jank STRING       The stage of EventLatency that the caused
---                                    the jank.
--- @column sub_cause_of_jank STRING   The stage of cause_of_jank that caused the
---                                    jank.
--- @column delayed_frame_count INT    How many vsyncs this frame missed its
---                                    deadline by.
--- @column frame_jank_ts INT          The start timestamp where frame
---                                    frame presentation was delayed.
--- @column frame_jank_dur INT         The duration in ms of the delay in frame
---                                    presentation.
-CREATE PERFETTO TABLE chrome_janky_event_latencies_v3 AS
+CREATE PERFETTO TABLE chrome_janky_event_latencies_v3(
+  -- The slice id.
+  id INT,
+  -- The start timestamp of the slice.
+  ts INT,
+  -- The duration of the slice.
+  dur INT,
+  -- The track_id for the slice.
+  track_id INT,
+  -- The name of the slice (EventLatency).
+  name STRING,
+  -- The stage of EventLatency that the caused the jank.
+  cause_of_jank STRING,
+  -- The stage of cause_of_jank that caused the jank.
+  sub_cause_of_jank STRING,
+  -- How many vsyncs this frame missed its deadline by.
+  delayed_frame_count INT,
+  -- The start timestamp where frame presentation was delayed.
+  frame_jank_ts INT,
+  -- The duration in ms of the delay in frame presentation.
+  frame_jank_dur INT
+) AS
 SELECT
   s.id,
   s.ts,
@@ -42,19 +47,22 @@
 
 -- Frame presentation interval is the delta between when the frame was supposed
 -- to be presented and when it was actually presented.
---
--- @column id INT                     Unique id.
--- @column ts INT                     The start timestamp of the slice.
--- @column dur INT                    The duration of the slice.
--- @column delayed_frame_count INT    How many vsyncs this frame missed its
---                                    deadline by.
--- @column cause_of_jank STRING       The stage of EventLatency that the caused
---                                    the jank.
--- @column sub_cause_of_jank STRING   The stage of cause_of_jank that caused the
---                                    jank.
--- @column event_latency_id STRING    The id of the associated event latency in
---                                    the slice table.
-CREATE VIEW chrome_janky_frame_presentation_intervals AS
+CREATE PERFETTO VIEW chrome_janky_frame_presentation_intervals(
+  -- Unique id.
+  id INT,
+  -- The start timestamp of the slice.
+  ts INT,
+  -- The duration of the slice.
+  dur INT,
+  -- How many vsyncs this frame missed its deadline by.
+  delayed_frame_count INT,
+  -- The stage of EventLatency that the caused the jank.
+  cause_of_jank INT,
+  -- The stage of cause_of_jank that caused the jank.
+  sub_cause_of_jank INT,
+  -- The id of the associated event latency in the slice table.
+  event_latency_id INT
+) AS
 SELECT
   ROW_NUMBER() OVER(ORDER BY frame_jank_ts) AS id,
   frame_jank_ts AS ts,
@@ -66,14 +74,20 @@
 FROM chrome_janky_event_latencies_v3;
 
 -- Scroll jank frame presentation stats for individual scrolls.
---
--- @column scroll_id INT              Id of the individual scroll.
--- @column missed_vsyncs INT          The number of missed vsyncs in the scroll.
--- @column frame_count INT            The number of frames in the scroll.
--- @column presented_frame_count INT  The number presented frames in the scroll.
--- @column janky_frame_count INT      The number of janky frames in the scroll.
--- @column janky_frame_percent FLOAT  The % of frames that janked in the scroll.
-CREATE VIEW chrome_scroll_stats AS
+CREATE PERFETTO VIEW chrome_scroll_stats(
+  -- Id of the individual scroll.
+  scroll_id INT,
+  -- The number of missed vsyncs in the scroll.
+  missed_vsyncs INT,
+  -- The number of frames in the scroll.
+  frame_count INT,
+  -- The number presented frames in the scroll.
+  presented_frame_count INT,
+  -- The number of janky frames in the scroll.
+  janky_frame_count INT,
+  -- The % of frames that janked in the scroll.
+  janky_frame_percent FLOAT
+) AS
 WITH vsyncs AS (
   SELECT
     COUNT() AS presented_vsync_count,
@@ -111,11 +125,14 @@
   USING (scroll_id);
 
 -- Defines slices for all of janky scrolling intervals in a trace.
---
--- @column id            The unique identifier of the janky interval.
--- @column ts            The start timestamp of the janky interval.
--- @column dur           The duration of the janky interval.
-CREATE PERFETTO TABLE chrome_scroll_jank_intervals_v3 AS
+CREATE PERFETTO TABLE chrome_scroll_jank_intervals_v3(
+  -- The unique identifier of the janky interval.
+  id INT,
+  -- The start timestamp of the janky interval.
+  ts INT,
+  -- The duration of the janky interval.
+  dur INT
+) AS
 -- Sub-table to retrieve all janky slice timestamps. Ordering calculations are
 -- based on timestamps rather than durations.
 WITH janky_latencies AS (
diff --git a/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql b/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql
index 4116e63..52e4f60 100644
--- a/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql
+++ b/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql
@@ -11,14 +11,20 @@
 
 -- Grabs all gesture updates with respective scroll ids and start/end
 -- timestamps, regardless of being coalesced.
---
--- @column ts                       The start timestamp of the scroll.
--- @column dur                      The duration of the scroll.
--- @column id                       Slice id for the scroll.
--- @column scroll_update_id         The id of the scroll update event.
--- @column scroll_id                The id of the scroll.
--- @column is_coalesced             Whether this input event was coalesced.
-CREATE PERFETTO TABLE chrome_gesture_scroll_updates AS
+CREATE PERFETTO TABLE chrome_gesture_scroll_updates(
+  -- The start timestamp of the scroll.
+  ts INT,
+  -- The duration of the scroll.
+  dur INT,
+  -- Slice id for the scroll.
+  id INT,
+  -- The id of the scroll update event.
+  scroll_update_id INT,
+  -- The id of the scroll.
+  scroll_id INT,
+  -- Whether this input event was coalesced.
+  is_coalesced BOOL
+) AS
 SELECT
   ts,
   dur,
@@ -43,18 +49,20 @@
 
 -- Scroll updates, corresponding to all input events that were converted to a
 -- presented scroll update.
---
--- @column id                       Minimum slice id for input presented in this
---                                  frame, the non coalesced input.
--- @column ts                       The start timestamp for producing the frame.
--- @column dur                      The duration between producing and
---                                  presenting the frame.
--- @column last_coalesced_input_ts  The timestamp of the last input that arrived
---                                  and got coalesced into the frame.
--- @column scroll_update_id         The id of the scroll update event, a unique
---                                  identifier to the gesture.
--- @column scroll_id                The id of the ongoing scroll.
-CREATE PERFETTO TABLE chrome_presented_gesture_scrolls AS
+CREATE PERFETTO TABLE chrome_presented_gesture_scrolls(
+  -- Minimum slice id for input presented in this frame, the non coalesced input.
+  id INT,
+  -- The start timestamp for producing the frame.
+  ts INT,
+  -- The duration between producing and presenting the frame.
+  dur INT,
+  -- The timestamp of the last input that arrived and got coalesced into the frame.
+  last_coalesced_input_ts INT,
+  -- The id of the scroll update event, a unique identifier to the gesture.
+  scroll_update_id INT,
+  -- The id of the ongoing scroll.
+  scroll_id INT
+) AS
 WITH
 scroll_updates_with_coalesce_info as MATERIALIZED (
   SELECT
@@ -93,11 +101,12 @@
 
 -- Associate every trace_id with it's perceived delta_y on the screen after
 -- prediction.
---
--- @column scroll_update_id         The id of the scroll update event.
--- @column delta_y                  The perceived delta_y on the screen post
---                                  prediction.
-CREATE PERFETTO TABLE chrome_scroll_updates_with_deltas AS
+CREATE PERFETTO TABLE chrome_scroll_updates_with_deltas(
+  -- The id of the scroll update event.
+  scroll_update_id INT,
+  -- The perceived delta_y on the screen post prediction.
+  delta_y INT
+) AS
 SELECT
   EXTRACT_ARG(arg_set_id, 'scroll_deltas.trace_id') AS scroll_update_id,
   EXTRACT_ARG(arg_set_id, 'scroll_deltas.provided_to_compositor_delta_y') AS delta_y
@@ -107,19 +116,21 @@
 -- Extract event latency timestamps, to later use it for joining
 -- with gesture scroll updates, as event latencies don't have trace
 -- ids associated with it.
---
--- @column ts                           Start timestamp for the EventLatency.
--- @column event_latency_id             Slice id of the EventLatency.
--- @column dur                          Duration of the EventLatency.
--- @column input_latency_end_ts         End timestamp for input aka the
---                                      timestamp of the LatchToSwapEnd
---                                      substage.
--- @column presentation_timestamp       Frame presentation timestamp aka the
---                                      timestamp of the
---                                      SwapEndToPresentationCompositorFrame
---                                      substage.
--- @column event_type                   EventLatency event type.
-CREATE PERFETTO TABLE chrome_gesture_scroll_event_latencies AS
+CREATE PERFETTO TABLE chrome_gesture_scroll_event_latencies(
+  -- Start timestamp for the EventLatency.
+  ts INT,
+  -- Slice id of the EventLatency.
+  event_latency_id INT,
+  -- Duration of the EventLatency.
+  dur INT,
+  -- End timestamp for input aka the timestamp of the LatchToSwapEnd substage.
+  input_latency_end_ts INT,
+  -- Frame presentation timestamp aka the timestamp of the
+  -- SwapEndToPresentationCompositorFrame substage.
+  presentation_timestamp INT,
+  -- EventLatency event type.
+  event_type INT
+) AS
 SELECT
   slice.ts,
   slice.id AS event_latency_id,
@@ -139,17 +150,24 @@
 -- latencies based on |LatchToSwapEnd| timestamp, as it's the
 -- end timestamp for both the gesture scroll update slice and
 -- the LatchToSwapEnd slice.
---
--- @column id                           ID of the frame.
--- @column ts                           Start timestamp of the frame.
--- @column last_coalesced_input_ts      The timestamp of the last coalesced
---                                      input.
--- @column scroll_id                    ID of the associated scroll.
--- @column scroll_update_id             ID of the associated scroll update.
--- @column event_latency_id             ID of the associated EventLatency.
--- @column dur                          Duration of the associated EventLatency.
--- @column presentation_timestamp       Frame presentation timestamp.
-CREATE PERFETTO TABLE chrome_full_frame_view AS
+CREATE PERFETTO TABLE chrome_full_frame_view(
+  -- ID of the frame.
+  id INT,
+  -- Start timestamp of the frame.
+  ts INT,
+  -- The timestamp of the last coalesced input.
+  last_coalesced_input_ts INT,
+  -- ID of the associated scroll.
+  scroll_id INT,
+  -- ID of the associated scroll update.
+  scroll_update_id INT,
+  -- ID of the associated EventLatency.
+  event_latency_id INT,
+  -- Duration of the associated EventLatency.
+  dur INT,
+  -- Frame presentation timestamp.
+  presentation_timestamp INT
+) AS
 SELECT
   frames.id,
   frames.ts,
@@ -165,19 +183,26 @@
   AND events.input_latency_end_ts = (frames.ts + frames.dur);
 
 -- Join deltas with EventLatency data.
---
--- @column id                           ID of the frame.
--- @column ts                           Start timestamp of the frame.
--- @column scroll_id                    ID of the associated scroll.
--- @column scroll_update_id             ID of the associated scroll update.
--- @column last_coalesced_input_ts      The timestamp of the last coalesced
---                                      input.
--- @column delta_y                      The perceived delta_y on the screen post
--- --                                   prediction.
--- @column event_latency_id             ID of the associated EventLatency.
--- @column dur                          Duration of the associated EventLatency.
--- @column presentation_timestamp       Frame presentation timestamp.
-CREATE PERFETTO TABLE chrome_full_frame_delta_view AS
+CREATE PERFETTO TABLE chrome_full_frame_delta_view(
+  -- ID of the frame.
+  id INT,
+  -- Start timestamp of the frame.
+  ts INT,
+  -- ID of the associated scroll.
+  scroll_id INT,
+  -- ID of the associated scroll update.
+  scroll_update_id INT,
+  -- The timestamp of the last coalesced input.
+  last_coalesced_input_ts INT,
+  -- The perceived delta_y on the screen post prediction.
+  delta_y INT,
+  -- ID of the associated EventLatency.
+  event_latency_id INT,
+  -- Duration of the associated EventLatency.
+  dur INT,
+  -- Frame presentation timestamp.
+  presentation_timestamp INT
+) AS
 SELECT
   frames.id,
   frames.ts,
@@ -194,25 +219,30 @@
 
 -- Group all gestures presented at the same timestamp together in
 -- a single row.
---
--- @column id                           ID of the frame.
--- @column max_start_ts                 The timestamp of the last coalesced
---                                      input.
--- @column min_start_ts                 The earliest frame start timestamp.
--- @column scroll_id                    ID of the associated scroll.
--- @column scroll_update_id             ID of the associated scroll update.
--- @column encapsulated_scroll_ids      All scroll updates associated with the
---                                      frame presentation timestamp.
--- @column total_delta                  Sum of all perceived delta_y values at
---                                      the frame presentation timestamp.
--- @column segregated_delta_y           Lists all of the perceived delta_y
---                                      values at the frame presentation
---                                      timestamp.
--- @column event_latency_id             ID of the associated EventLatency.
--- @column dur                          Maximum duration of the associated
---                                      EventLatency.
--- @column presentation_timestamp       Frame presentation timestamp.
-CREATE VIEW chrome_merged_frame_view AS
+CREATE PERFETTO VIEW chrome_merged_frame_view(
+  -- ID of the frame.
+  id INT,
+  -- The timestamp of the last coalesced input.
+  max_start_ts INT,
+  -- The earliest frame start timestamp.
+  min_start_ts INT,
+  -- ID of the associated scroll.
+  scroll_id INT,
+  -- ID of the associated scroll update.
+  scroll_update_id INT,
+  -- All scroll updates associated with the frame presentation timestamp.
+  encapsulated_scroll_ids INT,
+  -- Sum of all perceived delta_y values at the frame presentation timestamp.
+  total_delta INT,
+  -- Lists all of the perceived delta_y values at the frame presentation timestamp.
+  segregated_delta_y INT,
+  -- ID of the associated EventLatency.
+  event_latency_id INT,
+  -- Maximum duration of the associated EventLatency.
+  dur INT,
+  -- Frame presentation timestamp.
+  presentation_timestamp INT
+) AS
 SELECT
   id,
   MAX(last_coalesced_input_ts) AS max_start_ts,
@@ -232,31 +262,36 @@
 -- View contains all chrome presented frames during gesture updates
 -- while calculating delay since last presented which usually should
 -- equal to |VSYNC_INTERVAL| if no jank is present.
---
--- @column id                      gesture scroll slice id.
--- @column min_start_ts            OS timestamp of the first touch move arrival
---                                 within a frame.
--- @column max_start_ts            OS timestamp of the last touch move arrival
---                                 within a frame.
--- @column scroll_id               The scroll which the touch belongs to.
--- @column encapsulated_scroll_ids Trace ids of all frames presented in at this
---                                 vsync.
--- @column total_delta             Summation of all delta_y of all gesture
---                                 scrolls in this frame.
--- @column segregated_delta_y      All delta y of all gesture scrolls comma
---                                 separated, summing those gives |total_delta|.
--- @column event_latency_id        Event latency id of the presented frame.
--- @column dur                     Duration of the EventLatency.
--- @column presentation_timestamp  Timestamp at which the frame was shown on the
---                                 screen.
--- @column delay_since_last_frame  Time elapsed since the previous frame was
---                                 presented, usually equals |VSYNC| if no frame
---                                 drops happened.
--- @column delay_since_last_input  Difference in OS timestamps of inputs in the
---                                 current and the previous frame.
--- @column prev_event_latency_id   The event latency id that will be used as a
---                                 reference to determine the jank cause.
-CREATE VIEW chrome_frame_info_with_delay AS
+CREATE PERFETTO VIEW chrome_frame_info_with_delay(
+  -- gesture scroll slice id.
+  id INT,
+  -- OS timestamp of the first touch move arrival within a frame.
+  min_start_ts INT,
+  -- OS timestamp of the last touch move arrival within a frame.
+  max_start_ts INT,
+  -- The scroll which the touch belongs to.
+  scroll_id INT,
+  -- Trace ids of all frames presented in at this vsync.
+  encapsulated_scroll_ids INT,
+  -- Summation of all delta_y of all gesture scrolls in this frame.
+  total_delta INT,
+  -- All delta y of all gesture scrolls comma separated, summing those gives |total_delta|.
+  segregated_delta_y INT,
+  -- Event latency id of the presented frame.
+  event_latency_id INT,
+  -- Duration of the EventLatency.
+  dur INT,
+  -- Timestamp at which the frame was shown on the screen.
+  presentation_timestamp INT,
+  -- Time elapsed since the previous frame was presented, usually equals |VSYNC|
+  -- if no frame drops happened.
+  delay_since_last_frame INT,
+  -- Difference in OS timestamps of inputs in the current and the previous frame.
+  delay_since_last_input INT,
+  -- The event latency id that will be used as a reference to determine the
+  -- jank cause.
+  prev_event_latency_id INT
+) AS
 SELECT
   *,
   (presentation_timestamp -
@@ -271,28 +306,30 @@
 -- Calculate |VSYNC_INTERVAL| as the lowest delay between frames larger than
 -- zero.
 -- TODO(b/286222128): Emit this data from Chrome instead of calculating it.
---
--- @column vsync_interval           The lowest delay between frames larger than
---                                  zero.
-CREATE VIEW chrome_vsyncs AS
+CREATE PERFETTO VIEW chrome_vsyncs(
+  -- The lowest delay between frames larger than zero.
+  vsync_interval INT
+) AS
 SELECT
   MIN(delay_since_last_frame) AS vsync_interval
 FROM chrome_frame_info_with_delay
 WHERE delay_since_last_frame > 0;
 
 -- Filter the frame view only to frames that had missed vsyncs.
---
--- @column delay_since_last_frame Time elapsed since the previous frame was
---                                presented, will be more than |VSYNC| in this
---                                view.
--- @column event_latency_id       Event latency id of the presented frame.
--- @column vsync_interval         Vsync interval at the time of recording the
---                                trace.
--- @column hardware_class         Device brand and model.
--- @column scroll_id              The scroll corresponding to this frame.
--- @column prev_event_latency_id  The event latency id that will be used as a
---                                reference to determine the jank cause.
-CREATE VIEW chrome_janky_frames_no_cause AS
+CREATE PERFETTO VIEW chrome_janky_frames_no_cause(
+  -- Time elapsed since the previous frame was presented, will be more than |VSYNC| in this view.
+  delay_since_last_frame INT,
+  -- Event latency id of the presented frame.
+  event_latency_id INT,
+  -- Vsync interval at the time of recording the trace.
+  vsync_interval INT,
+  -- Device brand and model.
+  hardware_class STRING,
+  -- The scroll corresponding to this frame.
+  scroll_id INT,
+  -- The event latency id that will be used as a reference to determine the jank cause.
+  prev_event_latency_id INT
+) AS
 SELECT
   delay_since_last_frame,
   event_latency_id,
@@ -305,43 +342,50 @@
       AND delay_since_last_input < (select vsync_interval + vsync_interval / 2 from chrome_vsyncs);
 
 -- Janky frame information including the jank cause.
--- @column delay_since_last_frame Time elapsed since the previous frame was
---                                presented, will be more than |VSYNC| in this
---                                view.
--- @column event_latency_id       Event latency id of the presented frame.
--- @column vsync_interval         Vsync interval at the time of recording the
---                                trace.
--- @column hardware_class         Device brand and model.
--- @column scroll_id              The scroll corresponding to this frame.
--- @column prev_event_latency_id  The event latency id that will be used as a
---                                reference to determine the jank cause.
--- @column cause_id               Id of the slice corresponding to the offending stage.
-CREATE VIEW chrome_janky_frames_no_subcause AS
+CREATE PERFETTO VIEW chrome_janky_frames_no_subcause(
+  -- Time elapsed since the previous frame was presented, will be more than |VSYNC| in this view.
+  delay_since_last_frame INT,
+  -- Event latency id of the presented frame.
+  event_latency_id INT,
+  -- Vsync interval at the time of recording the trace.
+  vsync_interval INT,
+  -- Device brand and model.
+  hardware_class STRING,
+  -- The scroll corresponding to this frame.
+  scroll_id INT,
+  -- The event latency id that will be used as a reference to determine the jank cause.
+  prev_event_latency_id INT,
+  -- Id of the slice corresponding to the offending stage.
+  cause_id INT
+) AS
 SELECT
   *,
-  get_v3_jank_cause_id(event_latency_id, prev_event_latency_id) AS cause_id
+  chrome_get_v3_jank_cause_id(event_latency_id, prev_event_latency_id) AS cause_id
 FROM chrome_janky_frames_no_cause;
 
 -- Finds all causes of jank for all janky frames, and a cause of sub jank
 -- if the cause of jank was GPU related.
---
--- @column cause_of_jank          The reason the Vsync was missed.
--- @column sub_cause_of_jank      Further breakdown if the root cause was GPU
---                                related.
--- @column delay_since_last_frame Time elapsed since the previous frame was
---                                presented, will be more than |VSYNC| in this
---                                view.
--- @column event_latency_id       Event latency id of the presented frame.
--- @column vsync_interval         Vsync interval at the time of recording the
---                                trace.
--- @column hardware_class         Device brand and model.
--- @column scroll_id              The scroll corresponding to this frame.
-CREATE VIEW chrome_janky_frames AS
+CREATE PERFETTO VIEW chrome_janky_frames(
+  -- The reason the Vsync was missed.
+  cause_of_jank INT,
+  -- Further breakdown if the root cause was GPU related.
+  sub_cause_of_jank INT,
+  -- Time elapsed since the previous frame was presented, will be more than |VSYNC| in this view.
+  delay_since_last_frame INT,
+  -- Event latency id of the presented frame.
+  event_latency_id INT,
+  -- Vsync interval at the time of recording the trace.
+  vsync_interval INT,
+  -- Device brand and model.
+  hardware_class STRING,
+  -- The scroll corresponding to this frame.
+  scroll_id INT
+) AS
 SELECT
   slice_name_from_id(cause_id) AS cause_of_jank,
   slice_name_from_id(
     -- Getting sub-cause
-    get_v3_jank_cause_id(
+    chrome_get_v3_jank_cause_id(
       -- Here the cause itself is the parent.
       cause_id,
       -- Get the previous cause id as a child to the previous |EventLatency|.
@@ -359,9 +403,10 @@
 FROM chrome_janky_frames_no_subcause;
 
 -- Counting all unique frame presentation timestamps.
---
--- @column presentation_timestamp     The unique frame presentation timestamp.
-CREATE VIEW chrome_unique_frame_presentation_ts AS
+CREATE PERFETTO VIEW chrome_unique_frame_presentation_ts(
+  -- The unique frame presentation timestamp.
+  presentation_timestamp INT
+) AS
 SELECT DISTINCT
 presentation_timestamp
 FROM chrome_gesture_scroll_event_latencies;
@@ -369,11 +414,10 @@
 -- Dividing missed frames over total frames to get janky frame percentage.
 -- This represents the v3 scroll jank metrics.
 -- Reflects Event.Jank.DelayedFramesPercentage UMA metric.
---
--- @column delayed_frame_percentage       The percent of missed frames relative
---                                        to total frames - aka the percent of
---                                        janky frames.
-CREATE VIEW chrome_janky_frames_percentage AS
+CREATE PERFETTO VIEW chrome_janky_frames_percentage(
+  -- The percent of missed frames relative to total frames - aka the percent of janky frames.
+  delayed_frame_percentage FLOAT
+) AS
 SELECT
 (SELECT
   COUNT()
@@ -383,13 +427,16 @@
   FROM chrome_unique_frame_presentation_ts) * 100 AS delayed_frame_percentage;
 
 -- Number of frames and janky frames per scroll.
---
--- @column scroll_id                  The ID of the scroll.
--- @column num_frames                 The number of frames in the scroll.
--- @column num_janky_frames           The number of delayed/janky frames.
--- @column scroll_jank_percentage     The percentage of janky frames relative to
---                                    total frames.
-CREATE VIEW chrome_frames_per_scroll AS
+CREATE PERFETTO VIEW chrome_frames_per_scroll(
+  -- The ID of the scroll.
+  scroll_id INT,
+  -- The number of frames in the scroll.
+  num_frames INT,
+  -- The number of delayed/janky frames.
+  num_janky_frames INT,
+  -- The percentage of janky frames relative to total frames.
+  scroll_jank_percentage INT
+) AS
 WITH
   frames AS (
     SELECT scroll_id, COUNT(*) AS num_frames
@@ -414,17 +461,18 @@
   ON frames.scroll_id = janky_frames.scroll_id;
 
 -- Scroll jank causes per scroll.
---
--- @column scroll_id                   The ID of the scroll.
--- @column max_delay_since_last_frame  The maximum time a frame was delayed
---                                     after the presentation of the previous
---                                     frame.
--- @column vsync_interval              The expected vsync interval.
--- @column scroll_jank_causes          A proto amalgamation of each scroll
---                                     jank cause including cause name, sub
---                                     cause and the duration of the delay
---                                     since the previous frame was presented.
-CREATE VIEW chrome_causes_per_scroll AS
+CREATE PERFETTO VIEW chrome_causes_per_scroll(
+  -- The ID of the scroll.
+  scroll_id INT,
+  -- The maximum time a frame was delayed after the presentation of the previous
+  -- frame.
+  max_delay_since_last_frame INT,
+  -- The expected vsync interval.
+  vsync_interval INT,
+  -- A proto amalgamation of each scroll jank cause including cause name, sub
+  -- cause and the duration of the delay since the previous frame was presented.
+  scroll_jank_causes BYTES
+) AS
 SELECT
   scroll_id,
   MAX(1.0 * delay_since_last_frame / vsync_interval)
diff --git a/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3_cause.sql b/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3_cause.sql
index 9e07128..6936166 100644
--- a/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3_cause.sql
+++ b/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3_cause.sql
@@ -14,14 +14,13 @@
 -- the slice id of the slice named Z that is A's child, as no matching slice named Z was found
 -- under B, making 5 - 0 = 5 the maximum delta between both slice's direct children
 --
--- @arg janky_slice_id LONG The slice id of the parent slice that we want to
---                          cause among it's children.
--- @arg prev_slice_id  LONG The slice id of the parent slice that's the reference
---                          in comparison to |janky_slice_id|.
--- @ret breakdown_id   LONG The slice id of the breakdown that has the maximum
+-- @ret LONG The slice id of the breakdown that has the maximum
 --                          duration delta.
-CREATE PERFETTO FUNCTION get_v3_jank_cause_id(
+CREATE PERFETTO FUNCTION chrome_get_v3_jank_cause_id(
+  -- The slice id of the parent slice that we want to cause among it's children.
   janky_slice_id LONG,
+  -- The slice id of the parent slice that's the reference in comparison to
+  -- |janky_slice_id|.
   prev_slice_id LONG
 )
 RETURNS LONG AS
diff --git a/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql b/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql
index 80fba04..d51124ee 100644
--- a/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql
+++ b/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql
@@ -32,7 +32,7 @@
 INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_v3;
 
 -- Non-coalesced scroll update events and their timestamps.
-CREATE VIEW internal_non_coalesced_scrolls AS
+CREATE PERFETTO VIEW internal_non_coalesced_scrolls AS
 SELECT
   scroll_update_id,
   ts
@@ -58,7 +58,7 @@
 -- (internal_non_coalesced_scroll_updates) to get the timestamp of the event
 -- those deltas. This allows for ordering delta recordings to track them over
 -- time.
-CREATE VIEW internal_non_coalesced_deltas AS
+CREATE PERFETTO VIEW internal_non_coalesced_deltas AS
 SELECT
   scroll_update_id,
   ts,
@@ -85,7 +85,7 @@
 -- to get the timestamp of the event those deltas were coalesced into. This
 -- allows us to get the scaled coordinates for all of the input events
 -- (original input coordinates can't be used due to scaling).
-CREATE VIEW internal_coalesced_deltas AS
+CREATE PERFETTO VIEW internal_coalesced_deltas AS
 SELECT
   internal_scroll_update_coalesce_info.coalesced_to_scroll_update_id AS scroll_update_id,
   ts,
@@ -96,11 +96,13 @@
   USING (scroll_update_id);
 
 -- All of the presented frame scroll update ids.
--- @column arg_set_id                ID slice of the presented frame.
--- @column scroll_update_id          A scroll update id that was included in the
---                                   presented frame. There may be zero, one, or
---                                   more.
-CREATE VIEW chrome_deltas_presented_frame_scroll_update_ids AS
+CREATE PERFETTO VIEW chrome_deltas_presented_frame_scroll_update_ids(
+  -- ID slice of the presented frame.
+  arg_set_id INT,
+  -- A scroll update id that was included in the presented frame.
+  -- There may be zero, one, or more.
+  scroll_update_id INT
+) AS
 SELECT
   args.int_value AS scroll_update_id,
   slice.id
@@ -113,7 +115,7 @@
 -- When every GestureScrollUpdate event is processed, the offset set by the
 -- compositor is recorded. This offset is scaled to the device screen size, and
 -- can be used to calculate deltas.
-CREATE VIEW internal_presented_frame_offsets AS
+CREATE PERFETTO VIEW internal_presented_frame_offsets AS
 SELECT
   EXTRACT_ARG(arg_set_id, 'scroll_deltas.trace_id') AS scroll_update_id,
   EXTRACT_ARG(arg_set_id, 'scroll_deltas.visual_offset_y') AS visual_offset_y
@@ -124,14 +126,16 @@
 -- a scroll. This includes input events that were converted to scroll events
 -- which were presented (internal_non_coalesced_scrolls) and scroll events which
 -- were coalesced (internal_coalesced_deltas).
---
--- @column scroll_update_id          Trace Id associated with the scroll.
--- @column ts                        Timestamp the of the scroll input event.
--- @column delta_y                   The delta in raw coordinates between this
---                                   scroll update event and the previous.
--- @column offset_y                  The pixel offset of this scroll update
---                                   event compared to the previous one.
-CREATE PERFETTO TABLE chrome_scroll_input_offsets AS
+CREATE PERFETTO TABLE chrome_scroll_input_offsets(
+  -- Trace id associated with the scroll.
+  scroll_update_id INT,
+  -- Timestamp the of the scroll input event.
+  ts INT,
+  -- The delta in raw coordinates between this scroll update event and the previous.
+  delta_y INT,
+  -- The pixel offset of this scroll update event compared to the previous one.
+  offset_y INT
+) AS
 -- First collect all coalesced and non-coalesced deltas so that the offsets
 -- can be calculated from them in order of timestamp.
 WITH all_deltas AS (
@@ -161,15 +165,16 @@
 -- Calculate the total visual offset for all presented frames (non-coalesced
 -- scroll updates) that have raw deltas recorded. These visual offsets
 -- correspond with the inverse of the deltas for the presented frame.
-CREATE VIEW internal_preprocessed_presented_frame_offsets AS
+CREATE PERFETTO VIEW internal_preprocessed_presented_frame_offsets AS
 SELECT
-  internal_non_coalesced_scrolls.scroll_update_id,
-  internal_non_coalesced_scrolls.ts,
+  chrome_full_frame_view.scroll_update_id,
+  chrome_full_frame_view.presentation_timestamp AS ts,
   chrome_deltas_presented_frame_scroll_update_ids.id,
   internal_presented_frame_offsets.visual_offset_y -
     LAG(internal_presented_frame_offsets.visual_offset_y)
-    OVER (ORDER BY internal_non_coalesced_scrolls.ts) AS presented_frame_visual_offset_y
-FROM internal_non_coalesced_scrolls
+    OVER (ORDER BY chrome_full_frame_view.presentation_timestamp)
+      AS presented_frame_visual_offset_y
+FROM chrome_full_frame_view
 LEFT JOIN internal_scroll_deltas
   USING (scroll_update_id)
 LEFT JOIN chrome_deltas_presented_frame_scroll_update_ids
@@ -181,16 +186,18 @@
 -- The scrolling offsets for the actual (applied) scroll events. These are not
 -- necessarily inclusive of all user scroll events, rather those scroll events
 -- that are actually processed.
---
--- @column scroll_update_id          Trace Id associated with the scroll.
--- @column ts                        Presentation timestamp.
--- @column delta_y                   The delta in coordinates as processed by
---                                   Chrome between this scroll update event and
---                                   the previous.
--- @column offset_y                  The pixel offset of this scroll update (the
---                                   presented frame) compared to the previous
---                                   one.
-CREATE PERFETTO TABLE chrome_presented_scroll_offsets AS
+CREATE PERFETTO TABLE chrome_presented_scroll_offsets(
+  -- Trace Id associated with the scroll.
+  scroll_update_id INT,
+  -- Presentation timestamp.
+  ts INT,
+  -- The delta in coordinates as processed by Chrome between this scroll update
+  -- event and the previous.
+  delta_y INT,
+  -- The pixel offset of this scroll update (the presented frame) compared to
+  -- the previous one.
+  offset_y INT
+) AS
 WITH all_deltas AS (
   SELECT
     scroll_update_id,
diff --git a/base/tracing/stdlib/chrome/scroll_jank/utils.sql b/base/tracing/stdlib/chrome/scroll_jank/utils.sql
index b307cddb..64c5e00 100644
--- a/base/tracing/stdlib/chrome/scroll_jank/utils.sql
+++ b/base/tracing/stdlib/chrome/scroll_jank/utils.sql
@@ -17,7 +17,7 @@
 -- Function : function takes scroll ids of frames to verify it's from
 -- the same scroll, and makes sure the frame ts occured within the scroll
 -- timestamp of the neighbour and computes whether the frame was janky or not.
-CREATE PERFETTO FUNCTION is_janky_frame(cur_gesture_id LONG,
+CREATE PERFETTO FUNCTION internal_is_janky_frame(cur_gesture_id LONG,
                                       neighbour_gesture_id LONG,
                                       neighbour_ts LONG,
                                       cur_gesture_begin_ts LONG,
@@ -45,7 +45,7 @@
 --
 -- Returns the jank budget in percentage (i.e. 0.75) of vsync interval
 -- percentage.
-CREATE PERFETTO FUNCTION jank_budget(
+CREATE PERFETTO FUNCTION internal_jank_budget(
   cur_frame_exact FLOAT,
   prev_frame_exact FLOAT,
   next_frame_exact FLOAT
@@ -78,17 +78,17 @@
 -- names. For example, LongTaskTracker slices may have associated IPC
 -- metadata, or InterestingTask slices for input may have associated IPC to
 -- determine whether the task is fling/etc.
---
--- @arg name STRING            The name of slice.
--- @column interface_name      Name of the interface of the IPC call.
--- @column ipc_hash            Hash of the IPC call.
--- @column message_type        Message type (e.g. reply).
--- @column id                  The slice ID.
-CREATE PERFETTO FUNCTION chrome_select_long_task_slices(name STRING)
+CREATE PERFETTO FUNCTION chrome_select_long_task_slices(
+  -- The name of slice.
+  name STRING)
 RETURNS TABLE(
+  -- Name of the interface of the IPC call.
   interface_name STRING,
+  -- Hash of the IPC call.
   ipc_hash INT,
+  -- Message type (e.g. reply).
   message_type STRING,
+  -- The slice id.
   id INT
 ) AS
 SELECT
diff --git a/base/tracing/stdlib/chrome/speedometer.sql b/base/tracing/stdlib/chrome/speedometer.sql
index 718e202..e29811a 100644
--- a/base/tracing/stdlib/chrome/speedometer.sql
+++ b/base/tracing/stdlib/chrome/speedometer.sql
@@ -33,7 +33,7 @@
 -- @column suite_name    Suite name
 -- @column test_name     Test name
 -- @column mark_type     Type of mark (start, sync-end, async-end)
-CREATE VIEW internal_chrome_speedometer_mark
+CREATE PERFETTO VIEW internal_chrome_speedometer_mark
 AS
 WITH
   speedometer_21_suite_name(suite_name) AS (
@@ -98,14 +98,20 @@
 -- There are two intervals that are measured for every test: sync and async
 -- sync is the time between the start and sync-end marks, async is the time
 -- between the sync-end and async-end marks.
---
--- @column iteration     Speedometer iteration the mark belongs to.
--- @column suite_name    Suite name
--- @column test_name     Test name
--- @column measure_type  Type of the measure (sync or async)
--- @column ts            Start timestamp of the measure
--- @column dur           Duration of the measure
-CREATE VIEW chrome_speedometer_measure
+CREATE PERFETTO TABLE chrome_speedometer_measure(
+  -- Speedometer iteration the mark belongs to.
+  iteration INT,
+  -- Suite name
+  suite_name STRING,
+  -- Test name
+  test_name STRING,
+  -- Type of the measure (sync or async)
+  measure_type STRING,
+  -- Start timestamp of the measure
+  ts INT,
+  -- Duration of the measure
+  dur INT
+)
 AS
 WITH
   -- Get the 3 test timestamps (start, sync-end, async-end) in one row. Using a
@@ -161,17 +167,22 @@
 -- Speedometer would output, but note we use ns precision (Speedometer uses
 -- ~100us) so the actual values might differ a bit. Also note Speedometer
 -- returns the values in ms these here and in ns.
---
--- @column iteration Speedometer iteration.
--- @column ts        Start timestamp of the iteration
--- @column dur       Duration of the iteration
--- @column total     Total duration of the measures in this iteration
--- @column mean      Average suite duration for this iteration.
--- @column geomean   Geometric mean of the suite durations for this iteration.
--- @column score     Speedometer score for this iteration (The total score for a
---                   run in the average of all iteration scores).
-CREATE VIEW chrome_speedometer_iteration
-AS
+CREATE PERFETTO TABLE chrome_speedometer_iteration(
+  -- Speedometer iteration.
+  iteration INT,
+  -- Start timestamp of the iteration
+  ts INT,
+  -- Duration of the iteration
+  dur INT,
+  -- Total duration of the measures in this iteration
+  total INT,
+  -- Average suite duration for this iteration.
+  mean INT,
+  -- Geometric mean of the suite durations for this iteration.
+  geomean INT,
+  -- Speedometer score for this iteration (The total score for a run in the average of all iteration scores).
+  score INT
+) AS
 SELECT
   iteration,
   MIN(start) AS ts,
diff --git a/base/tracing/stdlib/chrome/tasks.sql b/base/tracing/stdlib/chrome/tasks.sql
index 766a9e5..f7242b4 100644
--- a/base/tracing/stdlib/chrome/tasks.sql
+++ b/base/tracing/stdlib/chrome/tasks.sql
@@ -248,14 +248,16 @@
 -- Chrome Java views. The view is considered interested if it's not a system
 -- (ContentFrameLayout) or generic library (CompositorViewHolder) views.
 --
--- @column filtered_name                Name of the view.
--- @column is_software_screenshot BOOL  Whether this slice is a part of non-accelerated
---                                      capture toolbar screenshot.
--- @column is_hardware_screenshot BOOL  Whether this slice is a part of accelerated
---                                      capture toolbar screenshot.
 -- TODO(altimin): Add "columns_from slice" annotation.
 -- TODO(altimin): convert this to EXTEND_TABLE when it becomes available.
-CREATE VIEW chrome_java_views AS
+CREATE PERFETTO VIEW chrome_java_views(
+  -- Name of the view.
+  filtered_name STRING,
+  -- Whether this slice is a part of non-accelerated capture toolbar screenshot.
+  is_software_screenshot BOOL,
+  -- Whether this slice is a part of accelerated capture toolbar screenshot.
+  is_hardware_screenshot BOOL
+) AS
 SELECT
   java_view.name AS filtered_name,
   java_view.is_software_screenshot,
@@ -265,7 +267,7 @@
 JOIN slice USING (id);
 
 -- A list of Choreographer tasks (Android frame generation) in Chrome.
-CREATE VIEW internal_chrome_choreographer_tasks
+CREATE PERFETTO VIEW internal_chrome_choreographer_tasks
 AS
 SELECT
   id,
@@ -319,7 +321,7 @@
 -- @column id INT            Slice id.
 -- @column kind STRING       Type of the task.
 -- @column java_views STRING Concatenated names of Java views used by the task.
-CREATE VIEW internal_chrome_slices_with_java_views AS
+CREATE PERFETTO VIEW internal_chrome_slices_with_java_views AS
 WITH
   -- Select UI thread BeginMainFrames (which are Chrome scheduler tasks) and
   -- Choreographer frames (which are looper tasks).
@@ -356,23 +358,38 @@
 ORDER BY id;
 
 -- A list of tasks executed by Chrome scheduler.
---
--- @column id                    Slice id.
--- @column name                  Name of the task.
--- @column ts                    Timestamp.
--- @column dur                   Duration.
--- @column utid                  Utid of the thread this task run on.
--- @column thread_name           Name of the thread this task run on.
--- @column upid                  Upid of the process of this task.
--- @column process_name          Name of the process of this task.
--- @column track_id              Same as slice.track_id.
--- @column depth                 Same as slice.depth.
--- @column parent_id             Same as slice.parent_id.
--- @column arg_set_id            Same as slice.arg_set_id.
--- @column thread_ts             Same as slice.thread_ts.
--- @column thread_dur            Same as slice.thread_dur.
--- @column posted_from           Source location where the PostTask was called.
-CREATE VIEW chrome_scheduler_tasks AS
+CREATE PERFETTO VIEW chrome_scheduler_tasks(
+  -- Slice id.
+  id INT,
+  -- Name of the task.
+  name STRING,
+  -- Timestamp.
+  ts INT,
+  -- Duration.
+  dur INT,
+  -- Utid of the thread this task run on.
+  utid INT,
+  -- Name of the thread this task run on.
+  thread_name STRING,
+  -- Upid of the process of this task.
+  upid INT,
+  -- Name of the process of this task.
+  process_name STRING,
+  -- Same as slice.track_id.
+  track_id INT,
+  -- Same as slice.depth.
+  depth INT,
+  -- Same as slice.parent_id.
+  parent_id INT,
+  -- Same as slice.arg_set_id.
+  arg_set_id INT,
+  -- Same as slice.thread_ts.
+  thread_ts INT,
+  -- Same as slice.thread_dur.
+  thread_dur INT,
+  -- Source location where the PostTask was called.
+  posted_from STRING
+) AS
 SELECT
   task.id,
   "chrome_scheduler_tasks" as type,
@@ -556,24 +573,38 @@
 -- A list of "Chrome tasks": top-level execution units (e.g. scheduler tasks /
 -- IPCs / system callbacks) run by Chrome. For a given thread, the slices
 -- corresponding to these tasks will not intersect.
---
--- @column id INT              Id for the given task, also the id of the slice this task corresponds to.
--- @column name STRING         Name for the given task.
--- @column task_type STRING    Type of the task (e.g. "scheduler").
--- @column thread_name STRING  Thread name.
--- @column utid INT            Utid.
--- @column process_name STRING Process name.
--- @column upid INT            Upid.
--- @column full_name STRING    Legacy alias for |task_name|.
--- @column ts INT              Alias of |slice.ts|.
--- @column dur INT             Alias of |slice.dur|.
--- @column track_id INT        Alias of |slice.track_id|.
--- @column category STRING     Alias of |slice.category|.
--- @column arg_set_id INT      Alias of |slice.arg_set_id|.
--- @column thread_ts INT       Alias of |slice.thread_ts|.
--- @column thread_dur INT      Alias of |slice.thread_dur|.
--- @column full_name STRING    Legacy alias for |name|.
-CREATE VIEW chrome_tasks AS
+CREATE PERFETTO VIEW chrome_tasks(
+  -- Id for the given task, also the id of the slice this task corresponds to.
+  id INT,
+  -- Name for the given task.
+  name STRING,
+  -- Type of the task (e.g. "scheduler").
+  task_type STRING,
+  -- Thread name.
+  thread_name STRING,
+  -- Utid.
+  utid INT,
+  -- Process name.
+  process_name STRING,
+  -- Upid.
+  upid INT,
+  -- Alias of |slice.ts|.
+  ts INT,
+  -- Alias of |slice.dur|.
+  dur INT,
+  -- Alias of |slice.track_id|.
+  track_id INT,
+  -- Alias of |slice.category|.
+  category INT,
+  -- Alias of |slice.arg_set_id|.
+  arg_set_id INT,
+  -- Alias of |slice.thread_ts|.
+  thread_ts INT,
+  -- Alias of |slice.thread_dur|.
+  thread_dur INT,
+  -- STRING    Legacy alias for |name|.
+  full_name STRING
+) AS
 SELECT
   cti.id,
   cti.name,
diff --git a/base/tracing/stdlib/chrome/vsync_intervals.sql b/base/tracing/stdlib/chrome/vsync_intervals.sql
index bf8c628..ebfade7 100644
--- a/base/tracing/stdlib/chrome/vsync_intervals.sql
+++ b/base/tracing/stdlib/chrome/vsync_intervals.sql
@@ -2,14 +2,23 @@
 -- Use of this source code is governed by a BSD-style license that can be
 -- found in the LICENSE file.
 
-DROP TABLE IF EXISTS chrome_vsync_intervals;
-
 -- A simple table that checks the time between VSync (this can be used to
 -- determine if we're refreshing at 90 FPS or 60 FPS).
 --
 -- Note: In traces without the "Java" category there will be no VSync
 --       TraceEvents and this table will be empty.
-CREATE PERFETTO TABLE chrome_vsync_intervals AS
+CREATE PERFETTO TABLE chrome_vsync_intervals(
+  -- Slice id of the vsync slice.
+  slice_id INT,
+  -- Timestamp of the vsync slice.
+  ts INT,
+  -- Duration of the vsync slice.
+  dur INT,
+  -- Track id of the vsync slice.
+  track_id INT,
+  -- Duration until next vsync arrives.
+  time_to_next_vsync INT
+) AS
 SELECT
   slice_id,
   ts,
@@ -22,19 +31,19 @@
 
 -- Function: compute the average Vysnc interval of the
 -- gesture (hopefully this would be either 60 FPS for the whole gesture or 90
--- FPS but that isn't always the case) on the given time segment.
--- If the trace doesn't contain the VSync TraceEvent we just fall back on
+-- FPS but that isnt always the case) on the given time segment.
+-- If the trace doesnt contain the VSync TraceEvent we just fall back on
 -- assuming its 60 FPS (this is the 1.6e+7 in the COALESCE which
 -- corresponds to 16 ms or 60 FPS).
 --
--- begin_ts: segment start time
--- end_ts: segment end time
-CREATE PERFETTO FUNCTION calculate_avg_vsync_interval(
+-- @ret FLOAT The average vsync interval on this time segment
+-- or 1.6e+7, if trace doesn't contain the VSync TraceEvent.
+CREATE PERFETTO FUNCTION chrome_calculate_avg_vsync_interval(
+  -- Interval start time.
   begin_ts LONG,
+  -- Interval end time.
   end_ts LONG
 )
--- Returns: the average Vysnc interval on this time segment
--- or 1.6e+7, if trace doesnt contain the VSync TraceEvent.
 RETURNS FLOAT AS
 SELECT
   COALESCE((
diff --git a/base/tracing/test/data/async-trace-1.json.sha256 b/base/tracing/test/data/async-trace-1.json.sha256
deleted file mode 100644
index 64b4b08..0000000
--- a/base/tracing/test/data/async-trace-1.json.sha256
+++ /dev/null
@@ -1 +0,0 @@
-758ad1ffc85d002ec1168b40bc3733793799d4ff6719341ef4f92d469c6e4d01
\ No newline at end of file
diff --git a/base/tracing/test/data/async-trace-2.json.sha256 b/base/tracing/test/data/async-trace-2.json.sha256
deleted file mode 100644
index a3ba889..0000000
--- a/base/tracing/test/data/async-trace-2.json.sha256
+++ /dev/null
@@ -1 +0,0 @@
-2da7fa65cce487d602e2ccfb333c9ecab298ef6e45b745c95240cebed150b577
\ No newline at end of file
diff --git a/base/tracing/test/data/chrome_android_systrace.pftrace.sha256 b/base/tracing/test/data/chrome_android_systrace.pftrace.sha256
deleted file mode 100644
index 63f5b7d..0000000
--- a/base/tracing/test/data/chrome_android_systrace.pftrace.sha256
+++ /dev/null
@@ -1 +0,0 @@
-a96005e5ee9059b89347573f7a7ca53097244fb3532956e0a62897ad77be2ddf
\ No newline at end of file
diff --git a/base/tracing/test/data/chrome_memory_snapshot.pftrace.sha256 b/base/tracing/test/data/chrome_memory_snapshot.pftrace.sha256
deleted file mode 100644
index c55016e..0000000
--- a/base/tracing/test/data/chrome_memory_snapshot.pftrace.sha256
+++ /dev/null
@@ -1 +0,0 @@
-4a06b393bf14147b25296797756a4185abf31510aca2db22ddb3c5dbd21123e4
\ No newline at end of file
diff --git a/base/tracing/test/data/chrome_rendering_desktop.pftrace.sha256 b/base/tracing/test/data/chrome_rendering_desktop.pftrace.sha256
deleted file mode 100644
index 28c7589..0000000
--- a/base/tracing/test/data/chrome_rendering_desktop.pftrace.sha256
+++ /dev/null
@@ -1 +0,0 @@
-f61971e42ea0ce0f6da71c87a0ab19da0e13deca0fa90c6bdc98782af01ae702
\ No newline at end of file
diff --git a/base/tracing/test/data/chrome_scroll_without_vsync.pftrace.sha256 b/base/tracing/test/data/chrome_scroll_without_vsync.pftrace.sha256
deleted file mode 100644
index 07deab4..0000000
--- a/base/tracing/test/data/chrome_scroll_without_vsync.pftrace.sha256
+++ /dev/null
@@ -1 +0,0 @@
-74890239a1042cb93a87b8b5b5d9942f821ed3cc0c1236e7734d45a550e3cde4
\ No newline at end of file
diff --git a/base/tracing/test/data/chrome_stack_traces_symbolized_trace.pftrace.sha256 b/base/tracing/test/data/chrome_stack_traces_symbolized_trace.pftrace.sha256
deleted file mode 100644
index 76156d4..0000000
--- a/base/tracing/test/data/chrome_stack_traces_symbolized_trace.pftrace.sha256
+++ /dev/null
@@ -1 +0,0 @@
-a3cb32a2faaef29b0b16c0f8242073beffdc6d0454e7a07a5e5466349f3c3125
\ No newline at end of file
diff --git a/base/tracing/test/data/chrome_touch_gesture_scroll.pftrace.sha256 b/base/tracing/test/data/chrome_touch_gesture_scroll.pftrace.sha256
deleted file mode 100644
index 9d04d5d..0000000
--- a/base/tracing/test/data/chrome_touch_gesture_scroll.pftrace.sha256
+++ /dev/null
@@ -1 +0,0 @@
-2fe40090c41ebeb5dc6ce0bea5bc9aef4d7f4cf7fd625209641e0c5ea2210fb7
\ No newline at end of file
diff --git a/base/tracing/test/data/cpu_powerups_1.pb.sha256 b/base/tracing/test/data/cpu_powerups_1.pb.sha256
new file mode 100644
index 0000000..04e0249
--- /dev/null
+++ b/base/tracing/test/data/cpu_powerups_1.pb.sha256
@@ -0,0 +1 @@
+70f5511ba0cd6ce1359e3cadb4d1d9301fb6e26be85158e3384b06f41418d386
diff --git a/base/tracing/test/data/event_latency_with_args.perfetto-trace.sha256 b/base/tracing/test/data/event_latency_with_args.perfetto-trace.sha256
deleted file mode 100644
index 6b5afdc..0000000
--- a/base/tracing/test/data/event_latency_with_args.perfetto-trace.sha256
+++ /dev/null
@@ -1 +0,0 @@
-c3d28fa97b1fcb515cacccdcddcda8981f5f2c6d20df682c59bcfdd8762954c2
\ No newline at end of file
diff --git a/base/tracing/test/data/example_android_trace_30s.pb.sha256 b/base/tracing/test/data/example_android_trace_30s.pb.sha256
deleted file mode 100644
index 83f6e45..0000000
--- a/base/tracing/test/data/example_android_trace_30s.pb.sha256
+++ /dev/null
@@ -1 +0,0 @@
-62656cc8ea2a624db95087850245d16453f0723f723ed2e329080e771bc1f82c
\ No newline at end of file
diff --git a/base/tracing/test/data/fling_with_input_delay.pftrace.sha256 b/base/tracing/test/data/fling_with_input_delay.pftrace.sha256
deleted file mode 100644
index c8ea1a2..0000000
--- a/base/tracing/test/data/fling_with_input_delay.pftrace.sha256
+++ /dev/null
@@ -1 +0,0 @@
-8c968b20e71481475a429399b4366bd796c527293218fe80789f9ed6ab9db5b4
\ No newline at end of file
diff --git a/base/tracing/test/data/long_task_tracking_trace.sha256 b/base/tracing/test/data/long_task_tracking_trace.sha256
deleted file mode 100644
index 6651eee6..0000000
--- a/base/tracing/test/data/long_task_tracking_trace.sha256
+++ /dev/null
@@ -1 +0,0 @@
-dbcb9f6baa0e89ea519b93aaee373e37a4b4e453a9d0f4ad8fef0279f25c33f2
\ No newline at end of file
diff --git a/base/tracing/test/data/scrolling_with_blocked_nonblocked_frames.pftrace.sha256 b/base/tracing/test/data/scrolling_with_blocked_nonblocked_frames.pftrace.sha256
deleted file mode 100644
index b2459c7..0000000
--- a/base/tracing/test/data/scrolling_with_blocked_nonblocked_frames.pftrace.sha256
+++ /dev/null
@@ -1 +0,0 @@
-25f78adb06ccbff3bc0d5a80993370c22eadc6685d66b005f1a35268752f847f
\ No newline at end of file
diff --git a/base/tracing/test/run_perfetto_diff_tests.py b/base/tracing/test/run_perfetto_diff_tests.py
index 6bbd894..7cbfbdcb 100755
--- a/base/tracing/test/run_perfetto_diff_tests.py
+++ b/base/tracing/test/run_perfetto_diff_tests.py
@@ -26,7 +26,7 @@
   parser.add_argument('--test-dir', type=str, required=True)
   parser.add_argument(
       '--trace-processor-shell', type=str, required=True)
-  parser.add_argument("--name-filter", type=str, required=False)
+  parser.add_argument("--name-filter", default="", type=str, required=False)
   parser.add_argument("--script", type=str, required=True)
   args, _ = parser.parse_known_args()
 
@@ -39,12 +39,8 @@
     "--chrome-track-event-descriptor", args.chrome_track_event_descriptor,
     "--override-sql-module", os.path.abspath(args.chrome_stdlib),
     "--test-dir", args.test_dir,
-    # TODO(b/301093584): This test fails with Chrome's trace_processor_shell
-    # most likely due to Chromium using a different version of sqlite.
-    # This name filter will be removed when fixed.
     "--name-filter",
-    "(?=^((?!ChromeScrollJank:frame_times_metric).)*$)(?={})"
-      .format(args.name_filter),
+    args.name_filter,
     args.trace_processor_shell,
   ]
 
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/actual_power_by_combined_rail_mode.py b/base/tracing/test/trace_processor/diff_tests/chrome/actual_power_by_combined_rail_mode.py
deleted file mode 100755
index ecb3bf4..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/actual_power_by_combined_rail_mode.py
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from os import sys
-
-import synth_common
-from synth_common import ms_to_ns
-
-trace = synth_common.create_trace()
-
-process_track1 = 1234
-process_track2 = 4567
-
-process_pid1 = 2345
-process_pid2 = 5678
-
-thread_track1 = 1235
-thread_track2 = 4568
-
-rail_track1 = 1236
-rail_track2 = 4569
-
-# Main threads have the same ID as the process
-thread_tid1 = process_pid1
-thread_tid2 = process_pid2
-
-seq1 = 9876
-seq2 = 9877
-
-thread1_counter = 60
-thread2_counter = 61
-
-packet = trace.add_packet()
-packet = trace.add_power_rails_desc(0, "PPVAR_VPH_PWR_RF")
-packet = trace.add_power_rails_desc(1, "PPVAR_VPH_PWR_S1C")
-
-trace.add_chrome_process_track_descriptor(process_track1, process_pid1)
-trace.add_chrome_process_track_descriptor(process_track2, process_pid2)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track1,
-    thread_track1,
-    trusted_packet_sequence_id=seq1,
-    counter_track=thread1_counter,
-    pid=process_pid1,
-    tid=thread_tid1,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track2,
-    thread_track2,
-    trusted_packet_sequence_id=seq2,
-    counter_track=thread2_counter,
-    pid=process_pid2,
-    tid=thread_tid2,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_track_descriptor(rail_track1, parent=process_track1)
-trace.add_track_descriptor(rail_track2, parent=process_track2)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=ms_to_ns(10),
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(10),
-    dur=ms_to_ns(20),
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(30),
-    dur=-1,
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_track_event_slice(
-    "task",
-    0,
-    ms_to_ns(10),
-    trusted_sequence_id=seq2,
-    cpu_start=0,
-    cpu_delta=ms_to_ns(10))
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(10),
-    dur=ms_to_ns(25),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(35),
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(45),
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-packet = trace.add_packet()
-
-# cellular
-packet = trace.add_power_rails_data(0, 0, 0)
-packet = trace.add_power_rails_data(10, 0, 0)
-packet = trace.add_power_rails_data(20, 0, 30)
-packet = trace.add_power_rails_data(30, 0, 50)
-packet = trace.add_power_rails_data(40, 0, 55)
-packet = trace.add_power_rails_data(50, 0, 56)
-packet = trace.add_power_rails_data(55, 0, 56)
-
-# cpu little cores
-packet = trace.add_power_rails_data(0, 1, 0)
-packet = trace.add_power_rails_data(10, 1, 20)
-packet = trace.add_power_rails_data(20, 1, 30)
-packet = trace.add_power_rails_data(30, 1, 40)
-packet = trace.add_power_rails_data(40, 1, 42)
-packet = trace.add_power_rails_data(50, 1, 60)
-packet = trace.add_power_rails_data(55, 1, 61)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_dropped_frames_metric_test.sql b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_dropped_frames_metric_test.sql
deleted file mode 100644
index ce4b7c7..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_dropped_frames_metric_test.sql
+++ /dev/null
@@ -1,7 +0,0 @@
--- Copyright 2023 The Chromium Authors
--- Use of this source code is governed by a BSD-style license that can be
--- found in the LICENSE file.
-
-SELECT RUN_METRIC('experimental/chrome_dropped_frames.sql');
-
-SELECT * FROM dropped_frames_with_process_info;
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_input_to_browser_intervals.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_input_to_browser_intervals.out
deleted file mode 100644
index 344a73e..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_input_to_browser_intervals.out
+++ /dev/null
@@ -1,4 +0,0 @@
-
-"window_start_ts","window_start_id","window_end_ts","window_end_id","blocked_gesture","upid","scroll_type"
-60934320005158,1480,60934321008158,1554,1,1,"blocking_touch_move"
-60934338798158,1942,60934342078158,2147,0,1,"regular"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_log_message_args_test.sql b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_log_message_args_test.sql
deleted file mode 100644
index 526d36e..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_log_message_args_test.sql
+++ /dev/null
@@ -1,11 +0,0 @@
--- Copyright 2023 The Chromium Authors
--- Use of this source code is governed by a BSD-style license that can be
--- found in the LICENSE file.
-
-SELECT
-  EXTRACT_ARG(s.arg_set_id, 'track_event.log_message') AS log_message,
-  EXTRACT_ARG(s.arg_set_id, 'track_event.log_message.function_name') AS function_name,
-  EXTRACT_ARG(s.arg_set_id, 'track_event.log_message.file_name') AS file_name,
-  EXTRACT_ARG(s.arg_set_id, 'track_event.log_message.line_number') AS line_number
-FROM
-  slice s;
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_long_tasks_delaying_input_processing_compare_default_test.sql b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_long_tasks_delaying_input_processing_compare_default_test.sql
deleted file mode 100644
index 253a1f8..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_long_tasks_delaying_input_processing_compare_default_test.sql
+++ /dev/null
@@ -1,21 +0,0 @@
--- Copyright 2023 The Chromium Authors
--- Use of this source code is governed by a BSD-style license that can be
--- found in the LICENSE file.
-
--- This test runs the on a trace that includes both LongTask tracking traces
--- and top-level traces. This test verifies that the default input processing
--- delay metric can be calculated while both scenarios are enabled. The output
--- should be consistent (same tasks) as the test for the LongTask version of the
--- metric - chrome_long_tasks_delaying_input_processing_test.sql
-
-SELECT RUN_METRIC(
-  'chrome/chrome_tasks_delaying_input_processing.sql',
-  'duration_causing_jank_ms', '4'
-);
-
-SELECT
-  full_name,
-  duration_ms,
-  slice_id
-FROM chrome_tasks_delaying_input_processing
-ORDER BY slice_id;
\ No newline at end of file
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_processes_android_systrace.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_processes_android_systrace.out
deleted file mode 100644
index f64d6893..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_processes_android_systrace.out
+++ /dev/null
@@ -1,10 +0,0 @@
-
-"pid","name","process_type"
-13315,"com.android.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:7","Renderer"
-10090,"com.android.chrome","Browser"
-9523,"org.chromium.chrome","Browser"
-10168,"com.android.chrome:privileged_process0","Gpu"
-9592,"org.chromium.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0","Renderer"
-9597,"org.chromium.chrome:privileged_process0","Gpu"
-13698,"com.android.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:12","Renderer"
-13736,"com.android.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:13","Renderer"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_processes_type_android_systrace.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_processes_type_android_systrace.out
deleted file mode 100644
index 63b7d4a..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_processes_type_android_systrace.out
+++ /dev/null
@@ -1,9 +0,0 @@
-"pid","name","chrome_process_type"
-9523,"org.chromium.chrome","Browser"
-9592,"org.chromium.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0","Renderer"
-9597,"org.chromium.chrome:privileged_process0","Gpu"
-10090,"com.android.chrome","Browser"
-10168,"com.android.chrome:privileged_process0","Gpu"
-13315,"com.android.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:7","Renderer"
-13698,"com.android.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:12","Renderer"
-13736,"com.android.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:13","Renderer"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range.textproto b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range.textproto
deleted file mode 100644
index d1115cfb..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range.textproto
+++ /dev/null
@@ -1,106 +0,0 @@
-# We have 3 threads, with 1 event each. The start time of the events are 11,
-# 12, and 13. The third thread has first_packet_on_sequence, so it should be
-# ignored for the reliable range computation.
-
-# Track descriptors for each thread.
-packet {
-  timestamp: 1
-  incremental_state_cleared: true
-  trusted_packet_sequence_id: 1
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 1
-      tid: 1
-    }
-    parent_uuid: 0
-  }
-}
-packet {
-  timestamp: 2
-  incremental_state_cleared: true
-  trusted_packet_sequence_id: 2
-  track_descriptor {
-    uuid: 2
-    thread {
-      pid: 2
-      tid: 2
-    }
-    parent_uuid: 0
-  }
-}
-packet {
-  timestamp: 3
-  incremental_state_cleared: true
-  first_packet_on_sequence: true
-  trusted_packet_sequence_id: 3
-  track_descriptor {
-    uuid: 3
-    thread {
-      pid: 3
-      tid: 3
-    }
-    parent_uuid: 0
-  }
-}
-
-# Slice begin events
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 11
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 1
-    name: "slice1"
-  }
-}
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 12
-  track_event {
-    track_uuid: 2
-    categories: "cat"
-    type: 1
-    name: "slice1"
-  }
-}
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 13
-  track_event {
-    track_uuid: 3
-    categories: "cat"
-    type: 1
-    name: "slice3"
-  }
-}
-
-# Slice end events
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 1011
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 2
-  }
-}
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 1012
-  track_event {
-    track_uuid: 2
-    categories: "cat"
-    type: 2
-  }
-}
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 1013
-  track_event {
-    track_uuid: 3
-    categories: "cat"
-    type: 2
-  }
-}
\ No newline at end of file
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_cropping.textproto b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_cropping.textproto
deleted file mode 100644
index f02a3e6..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_cropping.textproto
+++ /dev/null
@@ -1,113 +0,0 @@
-# This test is similar to chrome_reliable_range.textproto, but it has a cropping
-# packet, which takes precedence.
-
-packet {
-  timestamp: 0
-  trusted_packet_sequence_id: 1
-  incremental_state_cleared: true
-  track_event_range_of_interest {
-    start_us: 10
-  }
-}
-
-# Track descriptors for each thread.
-packet {
-  timestamp: 1
-  trusted_packet_sequence_id: 1
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 1
-      tid: 1
-    }
-    parent_uuid: 0
-  }
-}
-packet {
-  timestamp: 2
-  incremental_state_cleared: true
-  trusted_packet_sequence_id: 2
-  track_descriptor {
-    uuid: 2
-    thread {
-      pid: 2
-      tid: 2
-    }
-    parent_uuid: 0
-  }
-}
-packet {
-  timestamp: 3
-  incremental_state_cleared: true
-  first_packet_on_sequence: true
-  trusted_packet_sequence_id: 3
-  track_descriptor {
-    uuid: 3
-    thread {
-      pid: 3
-      tid: 3
-    }
-    parent_uuid: 0
-  }
-}
-
-# Slice begin events
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 11000
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 1
-    name: "slice1"
-  }
-}
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 12000
-  track_event {
-    track_uuid: 2
-    categories: "cat"
-    type: 1
-    name: "slice1"
-  }
-}
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 13000
-  track_event {
-    track_uuid: 3
-    categories: "cat"
-    type: 1
-    name: "slice3"
-  }
-}
-
-# Slice end events
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 1011000
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 2
-  }
-}
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 1012000
-  track_event {
-    track_uuid: 2
-    categories: "cat"
-    type: 2
-  }
-}
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 1013000
-  track_event {
-    track_uuid: 3
-    categories: "cat"
-    type: 2
-  }
-}
\ No newline at end of file
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_browser_main.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_browser_main.out
deleted file mode 100644
index 5fa75a75..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_browser_main.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"start","reason","debug_limiting_upid","debug_limiting_utid"
-1011,"Missing main thread for upid=1",1,1
\ No newline at end of file
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_browser_main.textproto b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_browser_main.textproto
deleted file mode 100644
index b7dac0b..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_browser_main.textproto
+++ /dev/null
@@ -1,50 +0,0 @@
-# There is a Browser process, but there's no Browser main thread.
-# The entire trace is unreliable.
-
-packet {
-  timestamp: 1
-  incremental_state_cleared: true
-  trusted_packet_sequence_id: 1
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 1
-      tid: 1
-    }
-    parent_uuid: 0
-  }
-}
-packet {
-    timestamp: 2
-    track_descriptor {
-        uuid: 2
-        process {
-            pid: 1
-        }
-        chrome_process {
-            process_type: PROCESS_BROWSER
-        }
-    }
-}
-
-# Slice begin event
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 11
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 1
-    name: "slice1"
-  }
-}
-# Slice end event
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 1011
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 2
-  }
-}
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_gpu_main.textproto b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_gpu_main.textproto
deleted file mode 100644
index 4465a30..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_gpu_main.textproto
+++ /dev/null
@@ -1,50 +0,0 @@
-# There is a Gpu process, but there's no Gpu main thread.
-# The entire trace is unreliable.
-
-packet {
-  timestamp: 1
-  incremental_state_cleared: true
-  trusted_packet_sequence_id: 1
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 1
-      tid: 1
-    }
-    parent_uuid: 0
-  }
-}
-packet {
-    timestamp: 2
-    track_descriptor {
-        uuid: 2
-        process {
-            pid: 1
-        }
-        chrome_process {
-            process_type: PROCESS_GPU
-        }
-    }
-}
-
-# Slice begin event
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 11
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 1
-    name: "slice1"
-  }
-}
-# Slice end event
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 1011
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 2
-  }
-}
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_processes.textproto b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_processes.textproto
deleted file mode 100644
index ffc093c..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_processes.textproto
+++ /dev/null
@@ -1,53 +0,0 @@
-packet {
-  timestamp: 0
-  incremental_state_cleared: true
-  trusted_packet_sequence_id: 1
-  track_event {
-    type: TYPE_INSTANT
-    name: "ActiveProcesses"
-    [perfetto.protos.ChromeTrackEvent.active_processes]: {
-      pid: 1
-      # Process 2 is marked as active, but its process descriptors are not
-      # present. Therefore, there is data loss until the end of the trace and
-      # the reliable range starts at the last packet's timestamp.
-      pid: 2
-    }
-  }
-}
-packet {
-  timestamp: 1
-  trusted_packet_sequence_id: 2
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 1
-      tid: 1
-    }
-    process {
-        pid: 1
-    }
-    parent_uuid: 0
-  }
-}
-
-# Slice begin event
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 11
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 1
-    name: "slice1"
-  }
-}
-# Slice end event
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 1011
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 2
-  }
-}
\ No newline at end of file
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_renderer_main.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_renderer_main.out
deleted file mode 100644
index 5fa75a75..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_renderer_main.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"start","reason","debug_limiting_upid","debug_limiting_utid"
-1011,"Missing main thread for upid=1",1,1
\ No newline at end of file
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_renderer_main.textproto b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_renderer_main.textproto
deleted file mode 100644
index 42cb741..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_missing_renderer_main.textproto
+++ /dev/null
@@ -1,50 +0,0 @@
-# There is a Renderer process, but there's no Renderer main thread.
-# The entire trace is unreliable.
-
-packet {
-  timestamp: 1
-  incremental_state_cleared: true
-  trusted_packet_sequence_id: 1
-  track_descriptor {
-    uuid: 1
-    thread {
-      pid: 1
-      tid: 1
-    }
-    parent_uuid: 0
-  }
-}
-packet {
-    timestamp: 2
-    track_descriptor {
-        uuid: 2
-        process {
-            pid: 1
-        }
-        chrome_process {
-            process_type: PROCESS_RENDERER
-        }
-    }
-}
-
-# Slice begin event
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 11
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 1
-    name: "slice1"
-  }
-}
-# Slice end event
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 1011
-  track_event {
-    track_uuid: 1
-    categories: "cat"
-    type: 2
-  }
-}
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_non_chrome_process.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_non_chrome_process.out
deleted file mode 100644
index f184dea4..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_non_chrome_process.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"start","reason","debug_limiting_upid","debug_limiting_utid"
-0,"[NULL]","[NULL]","[NULL]"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_test.sql b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_test.sql
deleted file mode 100644
index 26bc263..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_reliable_range_test.sql
+++ /dev/null
@@ -1,5 +0,0 @@
--- Copyright 2023 The Chromium Authors
--- Use of this source code is governed by a BSD-style license that can be
--- found in the LICENSE file.
-SELECT RUN_METRIC('chrome/chrome_reliable_range.sql');
-SELECT start, reason, debug_limiting_upid, debug_limiting_utid FROM chrome_reliable_range;
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_check.py b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_check.py
index 077a7f5e..445356e 100755
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_check.py
+++ b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_check.py
@@ -12,6 +12,7 @@
 import synth_common
 
 from synth_common import ms_to_ns
+
 trace = synth_common.create_trace()
 
 from chrome_scroll_helper import ChromeScrollHelper
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_helper.py b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_helper.py
index 06a69937..07a7b8b 100755
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_helper.py
+++ b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_helper.py
@@ -10,6 +10,7 @@
 import synth_common
 
 from synth_common import ms_to_ns
+
 trace = synth_common.create_trace()
 
 
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_jank_caused_by_scheduling_test.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_jank_caused_by_scheduling_test.out
deleted file mode 100644
index 968ff013..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_jank_caused_by_scheduling_test.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"full_name","total_duration_ms","total_thread_duration_ms","count","window_start_ts","window_end_ts","scroll_type"
-"viz.mojom.CompositorFrameSinkClient message (hash=50871626),viz.mojom.CompositorFrameSinkClient message (hash=3114070324),SingleThreadProxy::BeginMainFrame(java_views=ToolbarLayout),blink.mojom.WidgetInputHandler reply (hash=3392143105),cc.mojom.RenderFrameMetadataObserverClient message (hash=330497194),RunTask(posted_from=cc/scheduler/scheduler.cc:ScheduleBeginImplFrameDeadline),RunTask(posted_from=cc/scheduler/scheduler.cc:PostPendingBeginFrameTask),viz.mojom.FrameSinkManagerClient message (hash=532012934)",7.568000,6.745000,11,666960999011,666972176011,"regular"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_jank_v2.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_jank_v2.out
deleted file mode 100644
index b13137f4..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_scroll_jank_v2.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"scroll_processing_ms","scroll_jank_processing_ms","scroll_jank_percentage"
-12374.560000,154.217000,1.246242
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_speedometer_test.sql b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_speedometer_test.sql
deleted file mode 100644
index c5e8787c..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_speedometer_test.sql
+++ /dev/null
@@ -1,24 +0,0 @@
--- Copyright 2023 The Chromium Authors
--- Use of this source code is governed by a BSD-style license that can be
--- found in the LICENSE file.
-
-INCLUDE PERFETTO MODULE chrome.speedometer;
-
-SELECT
-  iteration,
-  ts,
-  dur,
-  total,
-  format('%.1f', mean) AS mean,
-  format('%.1f', geomean) AS geomean,
-  format('%.1f', score) AS score,
-  num_measurements
-FROM
-  chrome_speedometer_iteration,
-  (
-    SELECT iteration, COUNT(*) AS num_measurements
-    FROM chrome_speedometer_measure
-    GROUP BY iteration
-  )
-USING (iteration)
-ORDER BY iteration;
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_stack_samples_for_task_test.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_stack_samples_for_task_test.out
deleted file mode 100644
index 6e63af3..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_stack_samples_for_task_test.out
+++ /dev/null
@@ -1,11 +0,0 @@
-
-"description","ts","depth"
-"Scanned",696373965111470,0
-"tracing::TraceEventDataSource::OnAddLegacyTraceEvent(base::trace_event::TraceEvent*, bool, base::trace_event::TraceEventHandle*)",696373965111470,1
-"base::trace_event::TraceLog::AddTraceEventWithThreadIdAndTimestamps(char, unsigned char const*, char const*, char const*, unsigned long long, unsigned long long, int, base::TimeTicks const&, base::ThreadTicks const&, base::trace_event::TraceArguments*, unsigned int)",696373965111470,2
-"base::subtle::TimeTicksNowIgnoringOverride()",696373965111470,3
-"base::tracing::AutoThreadLocalBoolean::~AutoThreadLocalBoolean()",696373965111470,4
-"tracing::TraceEventDataSource::OnUpdateDuration(unsigned char const*, char const*, base::trace_event::TraceEventHandle, int, bool, base::TimeTicks const&, base::ThreadTicks const&, base::trace_event::ThreadInstructionCount)",696373965111470,5
-"content::ServiceWorkerRegistry::StoreUserData(long long, blink::StorageKey const&, std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&, base::OnceCallback<void (blink::ServiceWorkerStatusCode)>)",696373965111470,6
-"base::trace_event::TraceLog::UpdateTraceEventDuration(unsigned char const*, char const*, base::trace_event::TraceEventHandle)",696373965111470,7
-"XML_ParseBuffer",696373965111470,8
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_tasks_delaying_input_processing_test.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_tasks_delaying_input_processing_test.out
deleted file mode 100644
index 9edba72..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_tasks_delaying_input_processing_test.out
+++ /dev/null
@@ -1,5 +0,0 @@
-
-"full_name","duration_ms","thread_dur_ms"
-"FrameHost::BeginNavigation (unknown frame type)",16.111000,10.451000
-"Looper.dispatch: android.net.ConnectivityManager$CallbackHandler(null)",10.507000,0.878000
-"blink.mojom.PresentationService message (hash=3202951471)",22.524000,9.992000
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_threads.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_threads.out
deleted file mode 100644
index 217ab39..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_threads.out
+++ /dev/null
@@ -1,61 +0,0 @@
-
-"tid","name","is_main_thread","canonical_name"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-17547,"CrBrowserMain",1,"CrProcessMain"
-17578,"CrBrowserMain",1,"CrProcessMain"
-18245,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-18246,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18247,"Chrome_IOThread",0,"Chrome_IOThread"
-18248,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18249,"MemoryInfra",0,"MemoryInfra"
-18250,"[NULL]",1,"Unknown"
-18255,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18256,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18259,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18261,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18265,"AudioThread",0,"AudioThread"
-18273,"BrowserWatchdog",0,"BrowserWatchdog"
-18274,"NetworkService",0,"NetworkService"
-18275,"ThreadPoolSingleThreadSharedForegroundBlocking0",0,"ThreadPoolSingleThreadSharedForegroundBlocking0"
-18277,"[NULL]",1,"Unknown"
-18283,"CrRendererMain",0,"CrProcessMain"
-18304,"CrGpuMain",0,"CrProcessMain"
-18305,"CompositorTileWorker1",0,"CompositorTileWorker1"
-18306,"GpuWatchdog",0,"GpuWatchdog"
-18307,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-18308,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18309,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-18310,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18311,"VizCompositorThread",0,"VizCompositorThread"
-18312,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-18313,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18314,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-18315,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18316,"GpuMemoryThread",0,"GpuMemoryThread"
-18317,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18318,"Compositor",0,"Compositor"
-18319,"ThreadPoolSingleThreadSharedForegroundBlocking0",0,"ThreadPoolSingleThreadSharedForegroundBlocking0"
-18320,"CompositorTileWorker1",0,"CompositorTileWorker1"
-18322,"ThreadPoolSingleThreadForegroundBlocking1",0,"ThreadPoolSingleThreadForegroundBlocking1"
-18339,"Chrome_DevToolsHandlerThread",0,"Chrome_DevToolsHandlerThread"
-18483,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18508,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-18509,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18510,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18511,"Chrome_IOThread",0,"Chrome_IOThread"
-18512,"MemoryInfra",0,"MemoryInfra"
-18513,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18514,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18515,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18516,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18517,"AudioThread",0,"AudioThread"
-18518,"BrowserWatchdog",0,"BrowserWatchdog"
-18519,"NetworkService",0,"NetworkService"
-18520,"ThreadPoolSingleThreadSharedForegroundBlocking0",0,"ThreadPoolSingleThreadSharedForegroundBlocking0"
-18521,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18523,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18524,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-18525,"ThreadPoolSingleThreadForegroundBlocking1",0,"ThreadPoolSingleThreadForegroundBlocking1"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_threads_android_systrace.out b/base/tracing/test/trace_processor/diff_tests/chrome/chrome_threads_android_systrace.out
deleted file mode 100644
index 7c17db0..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/chrome_threads_android_systrace.out
+++ /dev/null
@@ -1,257 +0,0 @@
-
-"tid","name","is_main_thread","canonical_name"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-0,"[NULL]",0,"Unknown"
-9523,"CrBrowserMain",1,"CrProcessMain"
-9533,"[NULL]",0,"Unknown"
-9534,"[NULL]",0,"Unknown"
-9535,"[NULL]",0,"Unknown"
-9536,"[NULL]",0,"Unknown"
-9537,"[NULL]",0,"Unknown"
-9538,"[NULL]",0,"Unknown"
-9539,"[NULL]",0,"Unknown"
-9540,"[NULL]",0,"Unknown"
-9542,"[NULL]",0,"Unknown"
-9543,"[NULL]",0,"Unknown"
-9544,"[NULL]",0,"Unknown"
-9545,"[NULL]",0,"Unknown"
-9551,"[NULL]",0,"Unknown"
-9558,"[NULL]",0,"Unknown"
-9559,"[NULL]",0,"Unknown"
-9562,"[NULL]",0,"Unknown"
-9563,"[NULL]",0,"Unknown"
-9574,"HangWatcher",0,"HangWatcher"
-9575,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-9576,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-9579,"Chrome_IOThread",0,"Chrome_IOThread"
-9580,"[NULL]",0,"Unknown"
-9581,"[NULL]",0,"Unknown"
-9584,"[NULL]",0,"Unknown"
-9585,"[NULL]",0,"Unknown"
-9587,"NetworkService",0,"NetworkService"
-9588,"ThreadPoolSingleThreadSharedForegroundBlocking0",0,"ThreadPoolSingleThreadSharedForegroundBlocking0"
-9591,"[NULL]",0,"Unknown"
-9592,"[NULL]",1,"Unknown"
-9597,"[NULL]",1,"Unknown"
-9600,"[NULL]",0,"Unknown"
-9601,"[NULL]",0,"Unknown"
-9603,"[NULL]",0,"Unknown"
-9604,"[NULL]",0,"Unknown"
-9605,"[NULL]",0,"Unknown"
-9611,"[NULL]",0,"Unknown"
-9612,"[NULL]",0,"Unknown"
-9613,"[NULL]",0,"Unknown"
-9614,"[NULL]",0,"Unknown"
-9615,"[NULL]",0,"Unknown"
-9616,"[NULL]",0,"Unknown"
-9621,"[NULL]",0,"Unknown"
-9622,"[NULL]",0,"Unknown"
-9623,"[NULL]",0,"Unknown"
-9624,"[NULL]",0,"Unknown"
-9625,"[NULL]",0,"Unknown"
-9627,"[NULL]",0,"Unknown"
-9630,"[NULL]",0,"Unknown"
-9637,"[NULL]",0,"Unknown"
-9638,"[NULL]",0,"Unknown"
-9639,"[NULL]",0,"Unknown"
-9641,"[NULL]",0,"Unknown"
-9642,"[NULL]",0,"Unknown"
-9643,"[NULL]",0,"Unknown"
-9645,"[NULL]",0,"Unknown"
-9646,"[NULL]",0,"Unknown"
-9647,"CrRendererMain",0,"CrProcessMain"
-9654,"[NULL]",0,"Unknown"
-9655,"[NULL]",0,"Unknown"
-9666,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-9667,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-9668,"[NULL]",0,"Unknown"
-9670,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-9672,"[NULL]",0,"Unknown"
-9699,"[NULL]",0,"Unknown"
-9700,"[NULL]",0,"Unknown"
-9702,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-9706,"[NULL]",0,"Unknown"
-9707,"[NULL]",0,"Unknown"
-9708,"[NULL]",0,"Unknown"
-9709,"[NULL]",0,"Unknown"
-9710,"[NULL]",0,"Unknown"
-9711,"[NULL]",0,"Unknown"
-9712,"[NULL]",0,"Unknown"
-9713,"[NULL]",0,"Unknown"
-9761,"[NULL]",0,"Unknown"
-9934,"[NULL]",0,"Unknown"
-9990,"[NULL]",0,"Unknown"
-9994,"[NULL]",0,"Unknown"
-10016,"[NULL]",0,"Unknown"
-10070,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10090,"CrBrowserMain",1,"CrProcessMain"
-10099,"[NULL]",0,"Unknown"
-10100,"[NULL]",0,"Unknown"
-10101,"[NULL]",0,"Unknown"
-10102,"Jit thread pool",0,"Jit thread pool"
-10104,"HeapTaskDaemon",0,"HeapTaskDaemon"
-10105,"[NULL]",0,"Unknown"
-10106,"[NULL]",0,"Unknown"
-10107,"FinalizerWatchd",0,"FinalizerWatchd"
-10108,"[NULL]",0,"Unknown"
-10109,"Binder:10090_2",0,"Binder:10090_2"
-10110,"[NULL]",0,"Unknown"
-10111,"Profile Saver",0,"Profile Saver"
-10123,"queued-work-loo",0,"queued-work-loo"
-10124,"GoogleApiHandle",0,"GoogleApiHandle"
-10125,"RenderThread",0,"RenderThread"
-10126,"Chrome_ProcessL",0,"Chrome_ProcessL"
-10134,"[NULL]",0,"Unknown"
-10150,"GPU completion",0,"GPU completion"
-10152,"HangWatcher",0,"HangWatcher"
-10153,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-10154,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10156,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10157,"Chrome_IOThread",0,"Chrome_IOThread"
-10158,"MemoryInfra",0,"MemoryInfra"
-10159,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10161,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10162,"AudioThread",0,"AudioThread"
-10163,"BrowserWatchdog",0,"BrowserWatchdog"
-10164,"NetworkService",0,"NetworkService"
-10165,"ThreadPoolSingleThreadSharedForegroundBlocking0",0,"ThreadPoolSingleThreadSharedForegroundBlocking0"
-10168,"[NULL]",1,"Unknown"
-10178,"[NULL]",0,"Unknown"
-10179,"[NULL]",0,"Unknown"
-10180,"[NULL]",0,"Unknown"
-10181,"[NULL]",0,"Unknown"
-10182,"[NULL]",0,"Unknown"
-10183,"[NULL]",0,"Unknown"
-10184,"[NULL]",0,"Unknown"
-10185,"[NULL]",0,"Unknown"
-10186,"[NULL]",0,"Unknown"
-10187,"[NULL]",0,"Unknown"
-10188,"[NULL]",0,"Unknown"
-10189,"Binder:10168_3",0,"Binder:10168_3"
-10199,"[NULL]",0,"Unknown"
-10212,"CrGpuMain",0,"CrProcessMain"
-10213,"SAFE_BROWSING_U",0,"SAFE_BROWSING_U"
-10221,"GpuWatchdog",0,"GpuWatchdog"
-10230,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-10231,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10233,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-10235,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-10236,"VizCompositorThread",0,"VizCompositorThread"
-10239,"[NULL]",0,"Unknown"
-10245,"[NULL]",0,"Unknown"
-10246,"[NULL]",0,"Unknown"
-10255,"[NULL]",0,"Unknown"
-11045,"[NULL]",0,"Unknown"
-11134,"[NULL]",0,"Unknown"
-11354,"[NULL]",0,"Unknown"
-11355,"[NULL]",0,"Unknown"
-11897,"[NULL]",0,"Unknown"
-12527,"Binder:10090_4",0,"Binder:10090_4"
-12529,"[NULL]",0,"Unknown"
-12534,"Binder:10090_5",0,"Binder:10090_5"
-12535,"[NULL]",0,"Unknown"
-13212,"[NULL]",0,"Unknown"
-13213,"[NULL]",0,"Unknown"
-13248,"[NULL]",0,"Unknown"
-13299,"[NULL]",0,"Unknown"
-13315,"ocessService0:7",1,"ocessService0:7"
-13326,"Runtime worker ",0,"Runtime worker "
-13327,"Runtime worker ",0,"Runtime worker "
-13328,"Runtime worker ",0,"Runtime worker "
-13329,"Runtime worker ",0,"Runtime worker "
-13331,"Signal Catcher",0,"Signal Catcher"
-13332,"perfetto_hprof_",0,"perfetto_hprof_"
-13333,"ADB-JDWP Connec",0,"ADB-JDWP Connec"
-13334,"HeapTaskDaemon",0,"HeapTaskDaemon"
-13335,"ReferenceQueueD",0,"ReferenceQueueD"
-13336,"FinalizerDaemon",0,"FinalizerDaemon"
-13337,"FinalizerWatchd",0,"FinalizerWatchd"
-13339,"Binder:13315_1",0,"Binder:13315_1"
-13340,"Binder:13315_2",0,"Binder:13315_2"
-13341,"Binder:13315_3",0,"Binder:13315_3"
-13342,"CrRendererMain",0,"CrProcessMain"
-13343,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-13344,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13345,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13346,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13347,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-13348,"GpuMemoryThread",0,"GpuMemoryThread"
-13349,"Compositor",0,"Compositor"
-13350,"ThreadPoolSingl",0,"ThreadPoolSingl"
-13351,"CompositorTileWorker1",0,"CompositorTileWorker1"
-13353,"CompositorTileWorkerBackground",0,"CompositorTileWorkerBackground"
-13371,"[NULL]",0,"Unknown"
-13634,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13643,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13644,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13651,"ServiceWorker thread",0,"ServiceWorker thread"
-13655,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13669,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13670,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13671,"[NULL]",0,"Unknown"
-13672,"[NULL]",0,"Unknown"
-13673,"[NULL]",0,"Unknown"
-13696,"ThreadPoolForeg",0,"ThreadPoolForeg"
-13697,"CrGpuMain",0,"CrProcessMain"
-13698,"cessService0:12",1,"cessService0:12"
-13703,"Runtime worker ",0,"Runtime worker "
-13704,"Runtime worker ",0,"Runtime worker "
-13705,"Runtime worker ",0,"Runtime worker "
-13706,"Runtime worker ",0,"Runtime worker "
-13707,"Signal Catcher",0,"Signal Catcher"
-13708,"perfetto_hprof_",0,"perfetto_hprof_"
-13709,"ADB-JDWP Connec",0,"ADB-JDWP Connec"
-13710,"HeapTaskDaemon",0,"HeapTaskDaemon"
-13711,"ReferenceQueueD",0,"ReferenceQueueD"
-13712,"FinalizerDaemon",0,"FinalizerDaemon"
-13713,"FinalizerWatchd",0,"FinalizerWatchd"
-13714,"Binder:13698_1",0,"Binder:13698_1"
-13715,"Binder:13698_2",0,"Binder:13698_2"
-13716,"Binder:13698_3",0,"Binder:13698_3"
-13717,"CrRendererMain",0,"CrProcessMain"
-13718,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-13720,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13721,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13722,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13723,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-13724,"GpuMemoryThread",0,"GpuMemoryThread"
-13725,"Compositor",0,"Compositor"
-13726,"ThreadPoolSingl",0,"ThreadPoolSingl"
-13727,"CompositorTileWorker1",0,"CompositorTileWorker1"
-13728,"CompositorTileW",0,"CompositorTileW"
-13729,"ThreadPoolForeg",0,"ThreadPoolForeg"
-13736,"cessService0:13",1,"cessService0:13"
-13741,"Runtime worker ",0,"Runtime worker "
-13742,"Runtime worker ",0,"Runtime worker "
-13743,"Runtime worker ",0,"Runtime worker "
-13744,"Runtime worker ",0,"Runtime worker "
-13745,"Signal Catcher",0,"Signal Catcher"
-13746,"perfetto_hprof_",0,"perfetto_hprof_"
-13747,"ADB-JDWP Connec",0,"ADB-JDWP Connec"
-13748,"HeapTaskDaemon",0,"HeapTaskDaemon"
-13749,"ReferenceQueueD",0,"ReferenceQueueD"
-13750,"FinalizerDaemon",0,"FinalizerDaemon"
-13751,"FinalizerWatchd",0,"FinalizerWatchd"
-13752,"Binder:13736_1",0,"Binder:13736_1"
-13753,"Binder:13736_2",0,"Binder:13736_2"
-13754,"Binder:13736_3",0,"Binder:13736_3"
-13755,"CrRendererMain",0,"CrProcessMain"
-13756,"ThreadPoolServiceThread",0,"ThreadPoolServiceThread"
-13757,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13758,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13759,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13760,"Chrome_ChildIOThread",0,"Chrome_ChildIOThread"
-13761,"GpuMemoryThread",0,"GpuMemoryThread"
-13763,"Compositor",0,"Compositor"
-13765,"ThreadPoolSingl",0,"ThreadPoolSingl"
-13766,"CompositorTileWorker1",0,"CompositorTileWorker1"
-13767,"CompositorTileWorkerBackground",0,"CompositorTileWorkerBackground"
-13781,"CrGpuMain",0,"CrProcessMain"
-13795,"ThreadPoolForegroundWorker",0,"ThreadPoolForegroundWorker"
-13796,"ThreadPoolForeg",0,"ThreadPoolForeg"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/combined_rail_modes.py b/base/tracing/test/trace_processor/diff_tests/chrome/combined_rail_modes.py
deleted file mode 100755
index f6c4ee5..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/combined_rail_modes.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from os import sys
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-track1 = 1234
-track2 = 4567
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(track2, pid=2)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=10000,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=10000,
-    dur=20000,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=30000,
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=10000,
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=10000,
-    dur=25000,
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=25000,
-    dur=10000,
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=35000,
-    dur=10000,
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/cpu_time_by_combined_rail_mode.py b/base/tracing/test/trace_processor/diff_tests/chrome/cpu_time_by_combined_rail_mode.py
deleted file mode 100755
index 50fe7c4e..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/cpu_time_by_combined_rail_mode.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from os import sys
-
-import synth_common
-
-trace = synth_common.create_trace()
-
-process_track1 = 1234
-process_track2 = 4567
-
-process_pid1 = 2345
-process_pid2 = 5678
-
-thread_track1 = 1235
-thread_track2 = 4568
-
-rail_track1 = 1236
-rail_track2 = 4569
-
-# Main threads have the same ID as the process
-thread_tid1 = process_pid1
-thread_tid2 = process_pid2
-
-seq1 = 9876
-seq2 = 9877
-
-thread1_counter = 60
-thread2_counter = 61
-
-trace.add_chrome_process_track_descriptor(process_track1, process_pid1)
-trace.add_chrome_process_track_descriptor(process_track2, process_pid2)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track1,
-    thread_track1,
-    trusted_packet_sequence_id=seq1,
-    counter_track=thread1_counter,
-    pid=process_pid1,
-    tid=thread_tid1,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track2,
-    thread_track2,
-    trusted_packet_sequence_id=seq2,
-    counter_track=thread2_counter,
-    pid=process_pid2,
-    tid=thread_tid2,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_track_descriptor(rail_track1, parent=process_track1)
-trace.add_track_descriptor(rail_track2, parent=process_track2)
-
-trace.add_track_event_slice(
-    "task", 0, 5000, trusted_sequence_id=seq1, cpu_start=0, cpu_delta=10000)
-trace.add_track_event_slice(
-    "task",
-    5000,
-    5000,
-    trusted_sequence_id=seq1,
-    cpu_start=12000,
-    cpu_delta=4000)
-
-trace.add_track_event_slice(
-    "task",
-    10000,
-    6000,
-    trusted_sequence_id=seq1,
-    cpu_start=18000,
-    cpu_delta=2000)
-trace.add_track_event_slice(
-    "task",
-    16000,
-    4000,
-    trusted_sequence_id=seq1,
-    cpu_start=20000,
-    cpu_delta=7000)
-
-trace.add_track_event_slice(
-    "task",
-    30000,
-    10000,
-    trusted_sequence_id=seq1,
-    cpu_start=30000,
-    cpu_delta=1000)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=10000,
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=10000,
-    dur=20000,
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=30000,
-    dur=-1,
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_track_event_slice(
-    "task", 0, 10000, trusted_sequence_id=seq2, cpu_start=0, cpu_delta=10000)
-
-trace.add_track_event_slice(
-    "task",
-    10000,
-    15000,
-    trusted_sequence_id=seq2,
-    cpu_start=12000,
-    cpu_delta=1000)
-
-trace.add_track_event_slice(
-    "task",
-    35000,
-    10000,
-    trusted_sequence_id=seq2,
-    cpu_start=20000,
-    cpu_delta=20000)
-
-trace.add_track_event_slice(
-    "task",
-    45000,
-    10000,
-    trusted_sequence_id=seq2,
-    cpu_start=40000,
-    cpu_delta=1000)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=10000,
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=10000,
-    dur=25000,
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=35000,
-    dur=10000,
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=45000,
-    dur=10000,
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/estimated_power_by_combined_rail_mode.py b/base/tracing/test/trace_processor/diff_tests/chrome/estimated_power_by_combined_rail_mode.py
deleted file mode 100755
index cddba03f..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/estimated_power_by_combined_rail_mode.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from os import sys
-
-import synth_common
-from synth_common import ms_to_ns
-
-trace = synth_common.create_trace()
-
-process_track1 = 1234
-process_track2 = 4567
-
-process_pid1 = 2345
-process_pid2 = 5678
-
-thread_track1 = 1235
-thread_track2 = 4568
-
-rail_track1 = 1236
-rail_track2 = 4569
-
-# Main threads have the same ID as the process
-thread_tid1 = process_pid1
-thread_tid2 = process_pid2
-
-seq1 = 9876
-seq2 = 9877
-
-thread1_counter = 60
-thread2_counter = 61
-
-packet = trace.add_packet()
-packet.system_info.android_build_fingerprint = "google/sargo/foo"
-
-trace.add_chrome_process_track_descriptor(process_track1, process_pid1)
-trace.add_chrome_process_track_descriptor(process_track2, process_pid2)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track1,
-    thread_track1,
-    trusted_packet_sequence_id=seq1,
-    counter_track=thread1_counter,
-    pid=process_pid1,
-    tid=thread_tid1,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track2,
-    thread_track2,
-    trusted_packet_sequence_id=seq2,
-    counter_track=thread2_counter,
-    pid=process_pid2,
-    tid=thread_tid2,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-trace.add_track_descriptor(rail_track1, parent=process_track1)
-trace.add_track_descriptor(rail_track2, parent=process_track2)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=ms_to_ns(10),
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(10),
-    dur=ms_to_ns(20),
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(30),
-    dur=-1,
-    track=rail_track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(10),
-    dur=ms_to_ns(25),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(35),
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=ms_to_ns(45),
-    dur=ms_to_ns(10),
-    track=rail_track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-# Create process tree
-trace.add_packet()
-trace.add_process(1, 0, "init")
-trace.add_process(thread_tid1, 1, "Renderer")
-trace.add_process(thread_tid2, 1, "Renderer")
-
-packet = trace.add_packet()
-
-# Add scheduling and cpu frequency data
-trace.add_ftrace_packet(cpu=0)
-trace.add_sched(ts=0, prev_pid=0, next_pid=thread_tid1)
-trace.add_cpufreq(ts=ms_to_ns(0), freq=1708800, cpu=0)
-trace.add_cpufreq(ts=ms_to_ns(5), freq=1324800, cpu=0)
-trace.add_sched(ts=ms_to_ns(20), prev_pid=thread_tid1, next_pid=0)
-trace.add_sched(ts=ms_to_ns(30), prev_pid=0, next_pid=thread_tid1)
-trace.add_cpufreq(ts=ms_to_ns(30), freq=300000, cpu=0)
-trace.add_cpufreq(ts=ms_to_ns(35), freq=1708800, cpu=0)
-trace.add_sched(ts=ms_to_ns(40), prev_pid=thread_tid1, next_pid=0)
-
-trace.add_ftrace_packet(cpu=1)
-trace.add_sched(ts=0, prev_pid=0, next_pid=thread_tid2)
-trace.add_cpufreq(ts=ms_to_ns(0), freq=998400, cpu=1)
-trace.add_sched(ts=ms_to_ns(10), prev_pid=thread_tid2, next_pid=0)
-trace.add_sched(ts=ms_to_ns(35), prev_pid=0, next_pid=thread_tid2)
-trace.add_cpufreq(ts=ms_to_ns(35), freq=1708800, cpu=1)
-trace.add_sched(ts=ms_to_ns(47), prev_pid=thread_tid2, next_pid=0)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/event_latency_scroll_jank.out b/base/tracing/test/trace_processor/diff_tests/chrome/event_latency_scroll_jank.out
deleted file mode 100644
index effa4b0..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/event_latency_scroll_jank.out
+++ /dev/null
@@ -1,12 +0,0 @@
-
-"jank","next_jank","prev_jank","gesture_begin_ts","gesture_end_ts","ts","dur","event_type","next_ts","next_dur","prev_ts","prev_dur"
-1,0,1,3107579952792897,3107581649376897,3107580143766897,35454000,"INERTIAL_GESTURE_SCROLL_UPDATE",3107580152108897,35464000,3107580135417897,27100000
-1,1,0,3107578477792897,3107579903554897,3107578535792897,39440000,"GESTURE_SCROLL_UPDATE",3107578556443897,27153000,3107578527792897,39081000
-1,0,1,3107578477792897,3107579903554897,3107579191373897,35485000,"INERTIAL_GESTURE_SCROLL_UPDATE",3107579199700897,35521000,3107579183046897,27103000
-1,0,1,3107578477792897,3107579903554897,3107579600751897,43838000,"INERTIAL_GESTURE_SCROLL_UPDATE",3107579609175897,43757000,3107579592394897,35480000
-0,0,0,3107579952792897,3107581649376897,3107579952792897,25970000,"FIRST_GESTURE_SCROLL_UPDATE",3107579956792897,30333000,"[NULL]","[NULL]"
-0,0,0,3107579952792897,3107581649376897,3107579956792897,30333000,"GESTURE_SCROLL_UPDATE",3107579968792897,26657000,3107579952792897,25970000
-0,0,0,3107579952792897,3107581649376897,3107579968792897,26657000,"GESTURE_SCROLL_UPDATE",3107579976792897,27003000,3107579956792897,30333000
-0,0,0,3107579952792897,3107581649376897,3107579976792897,27003000,"GESTURE_SCROLL_UPDATE",3107579985792897,26361000,3107579968792897,26657000
-0,0,0,3107579952792897,3107581649376897,3107579985792897,26361000,"GESTURE_SCROLL_UPDATE",3107579993792897,26709000,3107579976792897,27003000
-0,0,0,3107579952792897,3107581649376897,3107579993792897,26709000,"GESTURE_SCROLL_UPDATE",3107579998792897,30183000,3107579985792897,26361000
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/event_latency_scroll_jank_cause.out b/base/tracing/test/trace_processor/diff_tests/chrome/event_latency_scroll_jank_cause.out
deleted file mode 100644
index 6fc5c2f..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/event_latency_scroll_jank_cause.out
+++ /dev/null
@@ -1,6 +0,0 @@
-
-"dur","ts","event_type","next_jank","prev_jank","next_delta_dur_ns","prev_delta_dur_ns","cause_of_jank","max_delta_dur_ns","sub_cause_of_jank"
-39440000,3107578535792897,"GESTURE_SCROLL_UPDATE",1,0,9233000,"[NULL]","SubmitCompositorFrameToPresentationCompositorFrame",9233000,"BufferReadyToLatch"
-35485000,3107579191373897,"INERTIAL_GESTURE_SCROLL_UPDATE",0,1,"[NULL]",7445000,"SubmitCompositorFrameToPresentationCompositorFrame",7445000,"BufferReadyToLatch"
-43838000,3107579600751897,"INERTIAL_GESTURE_SCROLL_UPDATE",0,1,"[NULL]",8059000,"SubmitCompositorFrameToPresentationCompositorFrame",8059000,"BufferReadyToLatch"
-35454000,3107580143766897,"INERTIAL_GESTURE_SCROLL_UPDATE",0,1,"[NULL]",7219000,"SubmitCompositorFrameToPresentationCompositorFrame",7219000,"StartDrawToSwapStart"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/event_latency_to_breakdowns.out b/base/tracing/test/trace_processor/diff_tests/chrome/event_latency_to_breakdowns.out
deleted file mode 100644
index 099e02b..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/event_latency_to_breakdowns.out
+++ /dev/null
@@ -1,32 +0,0 @@
-
-"event_latency_ts","event_latency_dur","event_type","GenerationToRendererCompositorNs","GenerationToBrowserMainNs","BrowserMainToRendererCompositorNs","RendererCompositorQueueingDelayNs","unknown_stages_seen"
-3107578415792897,17551000,"TOUCH_PRESSED",7945000,"[NULL]","[NULL]",108000,"[NULL]"
-3107578415792897,20411000,"GESTURE_TAP_DOWN",9648000,"[NULL]","[NULL]",33000,"[NULL]"
-3107578418792897,6034000,"TOUCH_MOVED",5803000,"[NULL]","[NULL]",34000,"[NULL]"
-3107578423792897,6439000,"TOUCH_MOVED",6192000,"[NULL]","[NULL]",82000,"[NULL]"
-3107578427792897,4318000,"TOUCH_MOVED",4189000,"[NULL]","[NULL]",34000,"[NULL]"
-3107578431792897,5754000,"TOUCH_MOVED",5407000,"[NULL]","[NULL]",87000,"[NULL]"
-3107578435792897,3983000,"TOUCH_MOVED",3857000,"[NULL]","[NULL]",28000,"[NULL]"
-3107578439792897,4734000,"TOUCH_MOVED",4550000,"[NULL]","[NULL]",57000,"[NULL]"
-3107578448792897,4346000,"TOUCH_MOVED",4085000,"[NULL]","[NULL]",79000,"[NULL]"
-3107578452792897,3863000,"TOUCH_MOVED",3702000,"[NULL]","[NULL]",36000,"[NULL]"
-3107578456792897,4743000,"TOUCH_MOVED",4579000,"[NULL]","[NULL]",50000,"[NULL]"
-3107578460792897,4516000,"TOUCH_MOVED",4389000,"[NULL]","[NULL]",32000,"[NULL]"
-3107578464792897,4709000,"TOUCH_MOVED",4525000,"[NULL]","[NULL]",62000,"[NULL]"
-3107578468792897,4876000,"TOUCH_MOVED",4751000,"[NULL]","[NULL]",31000,"[NULL]"
-3107578473792897,3960000,"TOUCH_MOVED",3792000,"[NULL]","[NULL]",53000,"[NULL]"
-3107578477792897,26678000,"GESTURE_TAP_CANCEL",5674000,"[NULL]","[NULL]",51000,"[NULL]"
-3107578477792897,3956000,"TOUCH_MOVED",3793000,"[NULL]","[NULL]",36000,"[NULL]"
-3107578477792897,6671000,"GESTURE_SCROLL_BEGIN","[NULL]",5477000,871000,24000,"[NULL]"
-3107578477792897,30595000,"FIRST_GESTURE_SCROLL_UPDATE","[NULL]",6101000,1077000,5608000,"[NULL]"
-3107578481792897,5625000,"TOUCH_MOVED",5463000,"[NULL]","[NULL]",45000,"[NULL]"
-3107578481792897,8937000,"GESTURE_SCROLL_UPDATE","[NULL]",5903000,455000,2428000,"[NULL]"
-3107578483992897,3438000,"TOUCH_PRESSED",788000,"[NULL]","[NULL]",14000,"[NULL]"
-3107578485792897,4373000,"TOUCH_MOVED",4213000,"[NULL]","[NULL]",45000,"[NULL]"
-3107578485792897,30948000,"GESTURE_SCROLL_UPDATE","[NULL]",5302000,979000,7100000,"[NULL]"
-3107578489792897,5294000,"TOUCH_MOVED",5191000,"[NULL]","[NULL]",53000,"[NULL]"
-3107578489792897,9525000,"GESTURE_SCROLL_UPDATE","[NULL]",5045000,454000,3882000,"[NULL]"
-3107578494792897,3912000,"TOUCH_MOVED",3821000,"[NULL]","[NULL]",41000,"[NULL]"
-3107578494792897,30309000,"GESTURE_SCROLL_UPDATE","[NULL]",3671000,1262000,7674000,"[NULL]"
-3107578498792897,7457000,"TOUCH_MOVED",7359000,"[NULL]","[NULL]",47000,"[NULL]"
-3107578498792897,8728000,"GESTURE_SCROLL_UPDATE","[NULL]",3560000,4430000,617000,"[NULL]"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/experimental_reliable_chrome_tasks_delaying_input_processing_test.out b/base/tracing/test/trace_processor/diff_tests/chrome/experimental_reliable_chrome_tasks_delaying_input_processing_test.out
deleted file mode 100644
index d5bf819..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/experimental_reliable_chrome_tasks_delaying_input_processing_test.out
+++ /dev/null
@@ -1,4 +0,0 @@
-
-"full_name","duration_ms","thread_dur_ms"
-"Looper.dispatch: android.net.ConnectivityManager$CallbackHandler(null)",10.507000,0.878000
-"blink.mojom.PresentationService message (hash=3202951471)",22.524000,9.992000
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/frame_times_metric.out b/base/tracing/test/trace_processor/diff_tests/chrome/frame_times_metric.out
deleted file mode 100644
index 3ae3370..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/frame_times_metric.out
+++ /dev/null
@@ -1,1210 +0,0 @@
-[perfetto.protos.frame_times] {
-  frame_time: 16.816
-  frame_time: 16.791
-  frame_time: 16.677
-  frame_time: 16.875
-  frame_time: 16.555
-  frame_time: 16.571
-  frame_time: 17.015
-  frame_time: 16.379
-  frame_time: 16.659
-  frame_time: 16.87
-  frame_time: 16.667
-  frame_time: 16.609
-  frame_time: 17.019
-  frame_time: 16.684
-  frame_time: 16.691
-  frame_time: 16.598
-  frame_time: 16.605
-  frame_time: 16.675
-  frame_time: 16.895
-  frame_time: 16.614
-  frame_time: 16.856
-  frame_time: 16.664
-  frame_time: 16.636
-  frame_time: 16.83
-  frame_time: 16.313
-  frame_time: 17.04
-  frame_time: 16.695
-  frame_time: 16.699
-  frame_time: 16.481
-  frame_time: 16.954
-  frame_time: 16.633
-  frame_time: 16.783
-  frame_time: 16.655
-  frame_time: 16.764
-  frame_time: 16.5
-  frame_time: 16.791
-  frame_time: 16.991
-  frame_time: 16.617
-  frame_time: 16.668
-  frame_time: 16.374
-  frame_time: 16.941
-  frame_time: 16.429
-  frame_time: 16.921
-  frame_time: 16.654
-  frame_time: 16.966
-  frame_time: 16.184
-  frame_time: 17.212
-  frame_time: 16.545
-  frame_time: 16.838
-  frame_time: 16.511
-  frame_time: 16.678
-  frame_time: 16.706
-  frame_time: 16.651
-  frame_time: 16.831
-  frame_time: 16.662
-  frame_time: 16.72
-  frame_time: 16.523
-  frame_time: 17.072
-  frame_time: 16.732
-  frame_time: 16.783
-  frame_time: 16.492
-  frame_time: 16.958
-  frame_time: 16.805
-  frame_time: 16.433
-  frame_time: 16.697
-  frame_time: 16.412
-  frame_time: 16.708
-  frame_time: 16.912
-  frame_time: 16.799
-  frame_time: 16.692
-  frame_time: 16.642
-  frame_time: 16.679
-  frame_time: 16.39
-  frame_time: 16.762
-  frame_time: 17.136
-  frame_time: 16.536
-  frame_time: 16.652
-  frame_time: 16.746
-  frame_time: 16.632
-  frame_time: 16.626
-  frame_time: 17.139
-  frame_time: 16.886
-  frame_time: 16.464
-  frame_time: 16.167
-  frame_time: 16.664
-  frame_time: 17.122
-  frame_time: 16.706
-  frame_time: 16.859
-  frame_time: 16.543
-  frame_time: 16.319
-  frame_time: 17.227
-  frame_time: 16.758
-  frame_time: 16.36
-  frame_time: 16.834
-  frame_time: 16.757
-  frame_time: 16.409
-  frame_time: 16.908
-  frame_time: 16.785
-  frame_time: 16.691
-  frame_time: 16.399
-  frame_time: 17.055
-  frame_time: 16.348
-  frame_time: 16.668
-  frame_time: 16.957
-  frame_time: 16.605
-  frame_time: 16.552
-  frame_time: 16.696
-  frame_time: 16.946
-  frame_time: 16.893
-  frame_time: 16.659
-  frame_time: 16.674
-  frame_time: 16.608
-  frame_time: 16.82
-  frame_time: 16.6
-  frame_time: 16.743
-  frame_time: 16.512
-  frame_time: 16.647
-  frame_time: 16.613
-  frame_time: 16.793
-  frame_time: 16.574
-  frame_time: 16.775
-  frame_time: 17.215
-  frame_time: 16.306
-  frame_time: 16.604
-  frame_time: 16.847
-  frame_time: 16.899
-  frame_time: 16.561
-  frame_time: 16.659
-  frame_time: 16.548
-  frame_time: 16.716
-  frame_time: 16.819
-  frame_time: 16.85
-  frame_time: 16.724
-  frame_time: 16.653
-  frame_time: 16.553
-  frame_time: 16.783
-  frame_time: 16.543
-  frame_time: 16.627
-  frame_time: 16.817
-  frame_time: 16.629
-  frame_time: 16.898
-  frame_time: 16.592
-  frame_time: 17.033
-  frame_time: 16.702
-  frame_time: 16.35
-  frame_time: 17.052
-  frame_time: 16.568
-  frame_time: 16.785
-  frame_time: 16.673
-  frame_time: 16.798
-  frame_time: 16.743
-  frame_time: 17.166
-  frame_time: 16.409
-  frame_time: 16.375
-  frame_time: 16.804
-  frame_time: 16.692
-  frame_time: 16.802
-  frame_time: 16.62
-  frame_time: 16.787
-  frame_time: 16.581
-  frame_time: 17.26
-  frame_time: 16.346
-  frame_time: 16.654
-  frame_time: 16.579
-  frame_time: 16.41
-  frame_time: 16.968
-  frame_time: 16.769
-  frame_time: 16.728
-  frame_time: 16.647
-  frame_time: 16.651
-  frame_time: 16.603
-  frame_time: 16.706
-  frame_time: 16.705
-  frame_time: 16.754
-  frame_time: 16.449
-  frame_time: 16.954
-  frame_time: 16.947
-  frame_time: 16.438
-  frame_time: 16.679
-  frame_time: 17.492
-  frame_time: 16.044
-  frame_time: 16.551
-  frame_time: 17.175
-  frame_time: 16.198
-  frame_time: 17.152
-  frame_time: 16.512
-  frame_time: 16.718
-  frame_time: 16.699
-  frame_time: 16.864
-  frame_time: 16.736
-  frame_time: 16.606
-  frame_time: 16.829
-  frame_time: 16.336
-  frame_time: 16.866
-  frame_time: 16.901
-  frame_time: 16.654
-  frame_time: 16.73
-  frame_time: 16.366
-  frame_time: 17.021
-  frame_time: 16.516
-  frame_time: 16.742
-  frame_time: 16.85
-  frame_time: 16.417
-  frame_time: 17.11
-  frame_time: 16.588
-  frame_time: 16.727
-  frame_time: 16.625
-  frame_time: 16.684
-  frame_time: 16.774
-  frame_time: 16.638
-  frame_time: 16.866
-  frame_time: 16.518
-  frame_time: 16.688
-  frame_time: 16.844
-  frame_time: 16.808
-  frame_time: 16.666
-  frame_time: 16.568
-  frame_time: 16.775
-  frame_time: 16.763
-  frame_time: 16.223
-  frame_time: 16.976
-  frame_time: 16.563
-  frame_time: 16.994
-  frame_time: 16.944
-  frame_time: 16.422
-  frame_time: 16.783
-  frame_time: 16.535
-  frame_time: 17.022
-  frame_time: 16.245
-  frame_time: 16.989
-  frame_time: 17.11
-  frame_time: 16.091
-  frame_time: 16.61
-  frame_time: 17.223
-  frame_time: 16.588
-  frame_time: 16.377
-  frame_time: 16.882
-  frame_time: 16.478
-  frame_time: 17.064
-  frame_time: 17.023
-  frame_time: 16.327
-  frame_time: 16.745
-  frame_time: 16.572
-  frame_time: 16.719
-  frame_time: 16.717
-  frame_time: 16.675
-  frame_time: 16.952
-  frame_time: 16.283
-  frame_time: 17.076
-  frame_time: 16.438
-  frame_time: 16.656
-  frame_time: 16.627
-  frame_time: 17.149
-  frame_time: 16.507
-  frame_time: 16.695
-  frame_time: 16.852
-  frame_time: 16.669
-  frame_time: 16.708
-  frame_time: 16.799
-  frame_time: 16.752
-  frame_time: 16.703
-  frame_time: 16.602
-  frame_time: 16.711
-  frame_time: 16.54
-  frame_time: 16.713
-  frame_time: 16.731
-  frame_time: 16.636
-  frame_time: 17.09
-  frame_time: 16.538
-  frame_time: 16.848
-  frame_time: 16.704
-  frame_time: 16.302
-  frame_time: 16.737
-  frame_time: 16.878
-  frame_time: 16.522
-  frame_time: 16.824
-  frame_time: 16.872
-  frame_time: 16.782
-  frame_time: 16.419
-  frame_time: 16.847
-  frame_time: 16.815
-  frame_time: 16.338
-  frame_time: 16.848
-  frame_time: 16.687
-  frame_time: 17.042
-  frame_time: 16.313
-  frame_time: 16.989
-  frame_time: 16.843
-  frame_time: 16.23
-  frame_time: 16.831
-  frame_time: 17.174
-  frame_time: 16.227
-  frame_time: 16.587
-  frame_time: 17.134
-  frame_time: 16.654
-  frame_time: 16.682
-  frame_time: 16.757
-  frame_time: 16.732
-  frame_time: 16.685
-  frame_time: 16.774
-  frame_time: 16.678
-  frame_time: 16.473
-  frame_time: 16.796
-  frame_time: 16.73
-  frame_time: 16.758
-  frame_time: 16.684
-  frame_time: 16.692
-  frame_time: 16.709
-  frame_time: 17.045
-  frame_time: 16.552
-  frame_time: 16.712
-  frame_time: 16.375
-  frame_time: 16.875
-  frame_time: 16.762
-  frame_time: 16.639
-  frame_time: 16.594
-  frame_time: 16.857
-  frame_time: 16.422
-  frame_time: 16.914
-  frame_time: 16.667
-  frame_time: 16.801
-  frame_time: 17.196
-  frame_time: 16.229
-  frame_time: 17.002
-  frame_time: 16.421
-  frame_time: 16.579
-  frame_time: 16.731
-  frame_time: 16.6
-  frame_time: 16.913
-  frame_time: 16.596
-  frame_time: 16.674
-  frame_time: 16.706
-  frame_time: 16.723
-  frame_time: 16.78
-  frame_time: 16.675
-  frame_time: 16.651
-  frame_time: 16.851
-  frame_time: 16.59
-  frame_time: 17.057
-  frame_time: 16.716
-  frame_time: 16.226
-  frame_time: 16.918
-  frame_time: 16.755
-  frame_time: 16.688
-  frame_time: 16.717
-  frame_time: 16.388
-  frame_time: 17.128
-  frame_time: 16.519
-  frame_time: 16.711
-  frame_time: 16.725
-  frame_time: 16.679
-  frame_time: 16.573
-  frame_time: 16.892
-  frame_time: 16.668
-  frame_time: 16.729
-  frame_time: 16.737
-  frame_time: 16.695
-  frame_time: 16.702
-  frame_time: 16.677
-  frame_time: 16.852
-  frame_time: 16.512
-  frame_time: 16.757
-  frame_time: 16.657
-  frame_time: 16.607
-  frame_time: 17.096
-  frame_time: 16.607
-  frame_time: 16.598
-  frame_time: 16.505
-  frame_time: 16.722
-  frame_time: 16.811
-  frame_time: 16.664
-  frame_time: 16.738
-  frame_time: 16.816
-  frame_time: 16.597
-  frame_time: 16.762
-  frame_time: 16.416
-  frame_time: 17.049
-  frame_time: 16.651
-  frame_time: 16.683
-  frame_time: 16.463
-  frame_time: 16.896
-  frame_time: 16.457
-  frame_time: 17.091
-  frame_time: 16.534
-  frame_time: 16.787
-  frame_time: 16.659
-  frame_time: 16.611
-  frame_time: 16.741
-  frame_time: 16.785
-  frame_time: 16.45
-  frame_time: 17.021
-  frame_time: 16.722
-  frame_time: 16.633
-  frame_time: 16.838
-  frame_time: 16.241
-  frame_time: 16.974
-  frame_time: 16.708
-  frame_time: 16.745
-  frame_time: 16.674
-  frame_time: 16.621
-  frame_time: 16.71
-  frame_time: 16.741
-  frame_time: 16.744
-  frame_time: 16.709
-  frame_time: 16.707
-  frame_time: 16.603
-  frame_time: 16.84
-  frame_time: 16.42
-  frame_time: 16.976
-  frame_time: 16.808
-  frame_time: 16.369
-  frame_time: 16.832
-  frame_time: 16.767
-  frame_time: 16.548
-  frame_time: 16.878
-  frame_time: 16.865
-  frame_time: 16.918
-  frame_time: 16.611
-  frame_time: 16.686
-  frame_time: 16.49
-  frame_time: 16.694
-  frame_time: 16.477
-  frame_time: 17.31
-  frame_time: 15.995
-  frame_time: 17.086
-  frame_time: 16.789
-  frame_time: 16.613
-  frame_time: 16.801
-  frame_time: 16.556
-  frame_time: 16.769
-  frame_time: 16.664
-  frame_time: 16.524
-  frame_time: 16.949
-  frame_time: 16.66
-  frame_time: 16.835
-  frame_time: 16.232
-  frame_time: 17.075
-  frame_time: 16.694
-  frame_time: 16.632
-  frame_time: 16.672
-  frame_time: 16.773
-  frame_time: 16.761
-  frame_time: 16.593
-  frame_time: 16.707
-  frame_time: 16.903
-  frame_time: 16.464
-  frame_time: 16.8
-  frame_time: 16.725
-  frame_time: 16.63
-  frame_time: 16.612
-  frame_time: 16.86
-  frame_time: 16.7
-  frame_time: 16.746
-  frame_time: 16.409
-  frame_time: 16.962
-  frame_time: 16.764
-  frame_time: 16.618
-  frame_time: 16.781
-  frame_time: 16.788
-  frame_time: 16.488
-  frame_time: 16.755
-  frame_time: 16.686
-  frame_time: 16.701
-  frame_time: 16.778
-  frame_time: 16.693
-  frame_time: 16.505
-  frame_time: 17.008
-  frame_time: 16.531
-  frame_time: 16.513
-  frame_time: 16.912
-  frame_time: 16.58
-  frame_time: 16.685
-  frame_time: 16.849
-  frame_time: 16.69
-  frame_time: 16.555
-  frame_time: 16.82
-  frame_time: 16.65
-  frame_time: 16.78
-  frame_time: 16.679
-  frame_time: 16.729
-  frame_time: 16.183
-  frame_time: 17.318
-  frame_time: 16.648
-  frame_time: 16.75
-  frame_time: 16.794
-  frame_time: 16.309
-  frame_time: 16.929
-  frame_time: 16.588
-  frame_time: 16.665
-  frame_time: 16.914
-  frame_time: 16.708
-  frame_time: 16.681
-  frame_time: 16.678
-  frame_time: 16.368
-  frame_time: 17.4
-  frame_time: 16.317
-  frame_time: 16.951
-  frame_time: 16.584
-  frame_time: 16.687
-  frame_time: 16.966
-  frame_time: 16.413
-  frame_time: 16.456
-  frame_time: 16.73
-  frame_time: 16.963
-  frame_time: 16.3
-  frame_time: 17.323
-  frame_time: 16.507
-  frame_time: 16.506
-  frame_time: 16.765
-  frame_time: 16.757
-  frame_time: 16.653
-  frame_time: 16.67
-  frame_time: 16.866
-  frame_time: 16.406
-  frame_time: 16.91
-  frame_time: 16.49
-  frame_time: 17.009
-  frame_time: 16.714
-  frame_time: 16.358
-  frame_time: 17.015
-  frame_time: 16.713
-  frame_time: 16.651
-  frame_time: 16.708
-  frame_time: 16.73
-  frame_time: 16.642
-  frame_time: 16.456
-  frame_time: 16.911
-  frame_time: 16.459
-  frame_time: 16.923
-  frame_time: 16.544
-  frame_time: 16.767
-  frame_time: 16.396
-  frame_time: 17.106
-  frame_time: 16.402
-  frame_time: 16.976
-  frame_time: 16.651
-  frame_time: 16.44
-  frame_time: 16.703
-  frame_time: 17.053
-  frame_time: 16.376
-  frame_time: 17.105
-  frame_time: 16.565
-  frame_time: 16.766
-  frame_time: 16.388
-  frame_time: 17.04
-  frame_time: 16.915
-  frame_time: 16.68
-  frame_time: 16.399
-  frame_time: 16.897
-  frame_time: 16.333
-  frame_time: 17.182
-  frame_time: 16.515
-  frame_time: 16.735
-  frame_time: 16.674
-  frame_time: 16.441
-  frame_time: 17.002
-  frame_time: 16.753
-  frame_time: 16.604
-  frame_time: 16.68
-  frame_time: 16.711
-  frame_time: 16.672
-  frame_time: 16.308
-  frame_time: 17.04
-  frame_time: 16.376
-  frame_time: 17.349
-  frame_time: 16.463
-  frame_time: 16.547
-  frame_time: 16.836
-  frame_time: 16.71
-  frame_time: 16.639
-  frame_time: 16.651
-  frame_time: 16.711
-  frame_time: 16.906
-  frame_time: 16.845
-  frame_time: 16.457
-  frame_time: 16.424
-  frame_time: 17.067
-  frame_time: 16.14
-  frame_time: 17.189
-  frame_time: 16.63
-  frame_time: 16.717
-  frame_time: 16.771
-  frame_time: 16.639
-  frame_time: 16.733
-  frame_time: 16.796
-  frame_time: 16.578
-  frame_time: 16.678
-  frame_time: 16.908
-  frame_time: 16.515
-  frame_time: 16.712
-  frame_time: 16.506
-  frame_time: 16.933
-  frame_time: 16.377
-  frame_time: 17.083
-  frame_time: 16.637
-  frame_time: 16.626
-  frame_time: 16.682
-  frame_time: 16.677
-  frame_time: 16.7
-  frame_time: 16.786
-  frame_time: 16.798
-  frame_time: 16.583
-  frame_time: 16.859
-  exp_frame_time: 16.707
-  exp_frame_time: 16.704
-  exp_frame_time: 16.791
-  exp_frame_time: 16.695
-  exp_frame_time: 16.895
-  exp_frame_time: 16.504
-  exp_frame_time: 16.723
-  exp_frame_time: 16.698
-  exp_frame_time: 16.703
-  exp_frame_time: 16.701
-  exp_frame_time: 16.626
-  exp_frame_time: 16.78
-  exp_frame_time: 16.702
-  exp_frame_time: 16.741
-  exp_frame_time: 16.673
-  exp_frame_time: 16.707
-  exp_frame_time: 16.703
-  exp_frame_time: 16.691
-  exp_frame_time: 16.707
-  exp_frame_time: 16.705
-  exp_frame_time: 16.716
-  exp_frame_time: 16.736
-  exp_frame_time: 16.673
-  exp_frame_time: 16.624
-  exp_frame_time: 16.789
-  exp_frame_time: 16.72
-  exp_frame_time: 16.695
-  exp_frame_time: 16.723
-  exp_frame_time: 16.693
-  exp_frame_time: 16.704
-  exp_frame_time: 16.716
-  exp_frame_time: 16.699
-  exp_frame_time: 16.71
-  exp_frame_time: 16.731
-  exp_frame_time: 16.692
-  exp_frame_time: 16.711
-  exp_frame_time: 16.701
-  exp_frame_time: 16.707
-  exp_frame_time: 16.708
-  exp_frame_time: 16.708
-  exp_frame_time: 16.717
-  exp_frame_time: 16.686
-  exp_frame_time: 16.709
-  exp_frame_time: 16.702
-  exp_frame_time: 16.71
-  exp_frame_time: 16.694
-  exp_frame_time: 16.711
-  exp_frame_time: 16.683
-  exp_frame_time: 16.724
-  exp_frame_time: 16.705
-  exp_frame_time: 16.713
-  exp_frame_time: 16.685
-  exp_frame_time: 16.708
-  exp_frame_time: 16.702
-  exp_frame_time: 16.714
-  exp_frame_time: 16.889
-  exp_frame_time: 16.519
-  exp_frame_time: 16.711
-  exp_frame_time: 16.712
-  exp_frame_time: 16.692
-  exp_frame_time: 16.706
-  exp_frame_time: 16.702
-  exp_frame_time: 16.699
-  exp_frame_time: 16.713
-  exp_frame_time: 16.726
-  exp_frame_time: 16.937
-  exp_frame_time: 16.441
-  exp_frame_time: 16.714
-  exp_frame_time: 16.619
-  exp_frame_time: 16.707
-  exp_frame_time: 16.702
-  exp_frame_time: 16.783
-  exp_frame_time: 16.61
-  exp_frame_time: 16.703
-  exp_frame_time: 16.722
-  exp_frame_time: 16.781
-  exp_frame_time: 16.627
-  exp_frame_time: 16.782
-  exp_frame_time: 16.682
-  exp_frame_time: 16.712
-  exp_frame_time: 16.714
-  exp_frame_time: 16.615
-  exp_frame_time: 16.793
-  exp_frame_time: 16.697
-  exp_frame_time: 16.707
-  exp_frame_time: 16.7
-  exp_frame_time: 16.702
-  exp_frame_time: 16.707
-  exp_frame_time: 16.698
-  exp_frame_time: 16.722
-  exp_frame_time: 16.716
-  exp_frame_time: 16.68
-  exp_frame_time: 16.703
-  exp_frame_time: 16.696
-  exp_frame_time: 16.708
-  exp_frame_time: 16.697
-  exp_frame_time: 16.627
-  exp_frame_time: 16.785
-  exp_frame_time: 16.716
-  exp_frame_time: 16.686
-  exp_frame_time: 16.7
-  exp_frame_time: 16.705
-  exp_frame_time: 16.706
-  exp_frame_time: 16.709
-  exp_frame_time: 16.699
-  exp_frame_time: 16.703
-  exp_frame_time: 16.718
-  exp_frame_time: 16.712
-  exp_frame_time: 16.705
-  exp_frame_time: 16.694
-  exp_frame_time: 16.708
-  exp_frame_time: 16.706
-  exp_frame_time: 16.717
-  exp_frame_time: 16.696
-  exp_frame_time: 16.699
-  exp_frame_time: 16.722
-  exp_frame_time: 16.685
-  exp_frame_time: 16.706
-  exp_frame_time: 16.712
-  exp_frame_time: 16.69
-  exp_frame_time: 16.725
-  exp_frame_time: 16.716
-  exp_frame_time: 16.683
-  exp_frame_time: 16.698
-  exp_frame_time: 16.691
-  exp_frame_time: 16.64
-  exp_frame_time: 16.776
-  exp_frame_time: 16.706
-  exp_frame_time: 16.716
-  exp_frame_time: 16.787
-  exp_frame_time: 16.63
-  exp_frame_time: 16.599
-  exp_frame_time: 16.724
-  exp_frame_time: 16.778
-  exp_frame_time: 16.63
-  exp_frame_time: 16.703
-  exp_frame_time: 16.787
-  exp_frame_time: 16.688
-  exp_frame_time: 16.73
-  exp_frame_time: 16.701
-  exp_frame_time: 16.695
-  exp_frame_time: 16.701
-  exp_frame_time: 16.714
-  exp_frame_time: 16.697
-  exp_frame_time: 16.706
-  exp_frame_time: 16.725
-  exp_frame_time: 16.705
-  exp_frame_time: 16.721
-  exp_frame_time: 16.663
-  exp_frame_time: 16.739
-  exp_frame_time: 16.717
-  exp_frame_time: 16.623
-  exp_frame_time: 16.804
-  exp_frame_time: 16.7
-  exp_frame_time: 16.697
-  exp_frame_time: 16.727
-  exp_frame_time: 16.714
-  exp_frame_time: 16.714
-  exp_frame_time: 16.689
-  exp_frame_time: 16.713
-  exp_frame_time: 16.708
-  exp_frame_time: 16.616
-  exp_frame_time: 16.722
-  exp_frame_time: 16.684
-  exp_frame_time: 16.718
-  exp_frame_time: 16.704
-  exp_frame_time: 16.706
-  exp_frame_time: 16.788
-  exp_frame_time: 16.627
-  exp_frame_time: 16.686
-  exp_frame_time: 16.717
-  exp_frame_time: 16.785
-  exp_frame_time: 16.702
-  exp_frame_time: 16.636
-  exp_frame_time: 17.081
-  exp_frame_time: 16.332
-  exp_frame_time: 16.703
-  exp_frame_time: 16.784
-  exp_frame_time: 16.712
-  exp_frame_time: 16.711
-  exp_frame_time: 16.797
-  exp_frame_time: 16.622
-  exp_frame_time: 16.717
-  exp_frame_time: 16.703
-  exp_frame_time: 16.704
-  exp_frame_time: 16.712
-  exp_frame_time: 16.691
-  exp_frame_time: 16.732
-  exp_frame_time: 16.702
-  exp_frame_time: 16.714
-  exp_frame_time: 16.708
-  exp_frame_time: 16.718
-  exp_frame_time: 16.704
-  exp_frame_time: 16.698
-  exp_frame_time: 16.706
-  exp_frame_time: 16.632
-  exp_frame_time: 16.786
-  exp_frame_time: 16.697
-  exp_frame_time: 16.722
-  exp_frame_time: 16.709
-  exp_frame_time: 16.711
-  exp_frame_time: 16.712
-  exp_frame_time: 16.711
-  exp_frame_time: 16.711
-  exp_frame_time: 16.7
-  exp_frame_time: 16.713
-  exp_frame_time: 16.712
-  exp_frame_time: 16.703
-  exp_frame_time: 16.74
-  exp_frame_time: 16.673
-  exp_frame_time: 16.704
-  exp_frame_time: 16.721
-  exp_frame_time: 16.723
-  exp_frame_time: 16.685
-  exp_frame_time: 16.707
-  exp_frame_time: 16.703
-  exp_frame_time: 16.714
-  exp_frame_time: 16.715
-  exp_frame_time: 16.7
-  exp_frame_time: 16.714
-  exp_frame_time: 16.717
-  exp_frame_time: 16.702
-  exp_frame_time: 16.711
-  exp_frame_time: 16.71
-  exp_frame_time: 16.631
-  exp_frame_time: 16.894
-  exp_frame_time: 16.599
-  exp_frame_time: 16.702
-  exp_frame_time: 16.633
-  exp_frame_time: 16.787
-  exp_frame_time: 16.631
-  exp_frame_time: 16.705
-  exp_frame_time: 16.774
-  exp_frame_time: 16.636
-  exp_frame_time: 16.775
-  exp_frame_time: 16.705
-  exp_frame_time: 16.628
-  exp_frame_time: 16.788
-  exp_frame_time: 16.693
-  exp_frame_time: 16.643
-  exp_frame_time: 16.702
-  exp_frame_time: 16.776
-  exp_frame_time: 16.71
-  exp_frame_time: 16.704
-  exp_frame_time: 16.637
-  exp_frame_time: 16.78
-  exp_frame_time: 16.632
-  exp_frame_time: 16.778
-  exp_frame_time: 16.705
-  exp_frame_time: 16.744
-  exp_frame_time: 16.678
-  exp_frame_time: 16.71
-  exp_frame_time: 16.637
-  exp_frame_time: 16.79
-  exp_frame_time: 16.699
-  exp_frame_time: 16.721
-  exp_frame_time: 16.701
-  exp_frame_time: 16.722
-  exp_frame_time: 16.702
-  exp_frame_time: 16.685
-  exp_frame_time: 16.741
-  exp_frame_time: 16.676
-  exp_frame_time: 16.707
-  exp_frame_time: 16.704
-  exp_frame_time: 16.71
-  exp_frame_time: 16.705
-  exp_frame_time: 16.7
-  exp_frame_time: 16.717
-  exp_frame_time: 16.695
-  exp_frame_time: 16.709
-  exp_frame_time: 16.713
-  exp_frame_time: 16.705
-  exp_frame_time: 16.715
-  exp_frame_time: 16.629
-  exp_frame_time: 16.797
-  exp_frame_time: 16.698
-  exp_frame_time: 16.735
-  exp_frame_time: 16.699
-  exp_frame_time: 16.702
-  exp_frame_time: 16.703
-  exp_frame_time: 16.706
-  exp_frame_time: 16.709
-  exp_frame_time: 16.684
-  exp_frame_time: 16.732
-  exp_frame_time: 16.704
-  exp_frame_time: 16.706
-  exp_frame_time: 16.711
-  exp_frame_time: 16.713
-  exp_frame_time: 16.713
-  exp_frame_time: 16.691
-  exp_frame_time: 16.714
-  exp_frame_time: 16.729
-  exp_frame_time: 16.702
-  exp_frame_time: 16.703
-  exp_frame_time: 16.709
-  exp_frame_time: 16.709
-  exp_frame_time: 16.723
-  exp_frame_time: 16.693
-  exp_frame_time: 16.71
-  exp_frame_time: 16.694
-  exp_frame_time: 16.739
-  exp_frame_time: 16.696
-  exp_frame_time: 16.695
-  exp_frame_time: 16.713
-  exp_frame_time: 16.7
-  exp_frame_time: 16.731
-  exp_frame_time: 16.715
-  exp_frame_time: 16.712
-  exp_frame_time: 16.694
-  exp_frame_time: 16.643
-  exp_frame_time: 16.767
-  exp_frame_time: 16.649
-  exp_frame_time: 16.785
-  exp_frame_time: 16.705
-  exp_frame_time: 16.637
-  exp_frame_time: 16.708
-  exp_frame_time: 16.783
-  exp_frame_time: 16.629
-  exp_frame_time: 16.708
-  exp_frame_time: 16.71
-  exp_frame_time: 16.714
-  exp_frame_time: 16.685
-  exp_frame_time: 16.718
-  exp_frame_time: 16.723
-  exp_frame_time: 16.701
-  exp_frame_time: 16.701
-  exp_frame_time: 16.707
-  exp_frame_time: 16.687
-  exp_frame_time: 16.805
-  exp_frame_time: 16.705
-  exp_frame_time: 16.706
-  exp_frame_time: 16.705
-  exp_frame_time: 16.7
-  exp_frame_time: 16.633
-  exp_frame_time: 16.711
-  exp_frame_time: 16.704
-  exp_frame_time: 16.706
-  exp_frame_time: 16.708
-  exp_frame_time: 16.694
-  exp_frame_time: 16.845
-  exp_frame_time: 16.662
-  exp_frame_time: 16.708
-  exp_frame_time: 16.706
-  exp_frame_time: 16.717
-  exp_frame_time: 16.615
-  exp_frame_time: 16.71
-  exp_frame_time: 16.715
-  exp_frame_time: 16.709
-  exp_frame_time: 16.709
-  exp_frame_time: 16.712
-  exp_frame_time: 16.702
-  exp_frame_time: 16.712
-  exp_frame_time: 16.78
-  exp_frame_time: 16.706
-  exp_frame_time: 16.631
-  exp_frame_time: 16.689
-  exp_frame_time: 16.731
-  exp_frame_time: 16.703
-  exp_frame_time: 16.778
-  exp_frame_time: 16.704
-  exp_frame_time: 16.701
-  exp_frame_time: 16.609
-  exp_frame_time: 16.703
-  exp_frame_time: 16.803
-  exp_frame_time: 16.628
-  exp_frame_time: 16.767
-  exp_frame_time: 16.631
-  exp_frame_time: 16.705
-  exp_frame_time: 16.7
-  exp_frame_time: 16.702
-  exp_frame_time: 16.781
-  exp_frame_time: 16.626
-  exp_frame_time: 16.69
-  exp_frame_time: 16.795
-  exp_frame_time: 16.738
-  exp_frame_time: 16.668
-  exp_frame_time: 16.728
-  exp_frame_time: 16.666
-  exp_frame_time: 16.604
-  exp_frame_time: 16.722
-  exp_frame_time: 16.698
-  exp_frame_time: 16.708
-  exp_frame_time: 16.702
-  exp_frame_time: 16.712
-  exp_frame_time: 16.781
-  exp_frame_time: 16.7
-  exp_frame_time: 16.704
-  exp_frame_time: 16.707
-  exp_frame_time: 16.625
-  exp_frame_time: 16.731
-  exp_frame_time: 16.744
-  exp_frame_time: 16.706
-  exp_frame_time: 16.637
-  exp_frame_time: 16.687
-  exp_frame_time: 16.722
-  exp_frame_time: 16.702
-  exp_frame_time: 16.708
-  exp_frame_time: 16.783
-  exp_frame_time: 16.637
-  exp_frame_time: 16.775
-  exp_frame_time: 16.71
-  exp_frame_time: 16.625
-  exp_frame_time: 16.708
-  exp_frame_time: 16.786
-  exp_frame_time: 16.633
-  exp_frame_time: 16.703
-  exp_frame_time: 16.723
-  exp_frame_time: 16.697
-  exp_frame_time: 16.711
-  exp_frame_time: 16.706
-  exp_frame_time: 16.79
-  exp_frame_time: 16.705
-  exp_frame_time: 16.627
-  exp_frame_time: 16.706
-  exp_frame_time: 16.7
-  exp_frame_time: 16.705
-  exp_frame_time: 16.695
-  exp_frame_time: 16.719
-  exp_frame_time: 16.782
-  exp_frame_time: 16.69
-  exp_frame_time: 16.709
-  exp_frame_time: 16.698
-  exp_frame_time: 16.71
-  exp_frame_time: 16.608
-  exp_frame_time: 16.798
-  exp_frame_time: 16.694
-  exp_frame_time: 16.709
-  exp_frame_time: 16.702
-  exp_frame_time: 16.702
-  exp_frame_time: 16.752
-  exp_frame_time: 16.636
-  exp_frame_time: 16.706
-  exp_frame_time: 16.697
-  exp_frame_time: 16.697
-  exp_frame_time: 16.71
-  exp_frame_time: 16.681
-  exp_frame_time: 16.718
-  exp_frame_time: 16.71
-  exp_frame_time: 16.624
-  exp_frame_time: 16.793
-  exp_frame_time: 16.687
-  exp_frame_time: 16.714
-  exp_frame_time: 16.625
-  exp_frame_time: 16.781
-  exp_frame_time: 16.705
-  exp_frame_time: 16.727
-  exp_frame_time: 16.661
-  exp_frame_time: 16.776
-  exp_frame_time: 16.58
-  exp_frame_time: 16.778
-  exp_frame_time: 16.693
-  exp_frame_time: 16.707
-  exp_frame_time: 16.792
-  exp_frame_time: 16.613
-  exp_frame_time: 16.71
-  exp_frame_time: 16.705
-  exp_frame_time: 16.703
-  exp_frame_time: 16.699
-  exp_frame_time: 16.718
-  exp_frame_time: 16.7
-  exp_frame_time: 16.693
-  exp_frame_time: 16.706
-  exp_frame_time: 16.629
-  exp_frame_time: 16.919
-  exp_frame_time: 16.563
-  exp_frame_time: 16.637
-  exp_frame_time: 16.769
-  exp_frame_time: 16.71
-  exp_frame_time: 16.734
-  exp_frame_time: 16.656
-  exp_frame_time: 16.716
-  exp_frame_time: 16.626
-  exp_frame_time: 16.783
-  exp_frame_time: 16.699
-  exp_frame_time: 16.696
-  exp_frame_time: 16.632
-  exp_frame_time: 16.782
-  exp_frame_time: 16.704
-  exp_frame_time: 16.699
-  exp_frame_time: 16.699
-  exp_frame_time: 16.699
-  exp_frame_time: 16.645
-  exp_frame_time: 16.774
-  exp_frame_time: 16.704
-  exp_frame_time: 16.63
-  exp_frame_time: 16.703
-  exp_frame_time: 16.713
-  exp_frame_time: 16.778
-  exp_frame_time: 16.709
-  exp_frame_time: 16.701
-  exp_frame_time: 16.697
-  exp_frame_time: 16.638
-  exp_frame_time: 16.705
-  exp_frame_time: 16.702
-  exp_frame_time: 16.698
-  exp_frame_time: 16.862
-  exp_frame_time: 16.635
-  exp_frame_time: 16.691
-  exp_frame_time: 16.734
-  exp_frame_time: 16.603
-  exp_frame_time: 16.794
-  exp_frame_time: 16.706
-  exp_frame_time: 16.712
-  exp_frame_time: 16.689
-  exp_frame_time: 16.71
-  exp_frame_time: 16.703
-  exp_frame_time: 16.621
-  exp_frame_time: 16.772
-  exp_frame_time: 16.694
-  exp_frame_time: 16.705
-  exp_frame_time: 16.694
-  exp_frame_time: 16.708
-  exp_frame_time: 16.695
-  exp_frame_time: 16.708
-  exp_frame_time: 16.992
-  exp_frame_time: 16.403
-  exp_frame_time: 16.703
-  exp_frame_time: 16.713
-  exp_frame_time: 16.693
-  exp_frame_time: 16.691
-  exp_frame_time: 16.687
-  exp_frame_time: 16.717
-  exp_frame_time: 16.633
-  exp_frame_time: 16.766
-  exp_frame_time: 16.69
-  exp_frame_time: 16.7
-  exp_frame_time: 16.699
-  exp_frame_time: 16.637
-  exp_frame_time: 16.704
-  exp_frame_time: 16.775
-  exp_frame_time: 16.707
-  exp_frame_time: 16.636
-  exp_frame_time: 16.785
-  exp_frame_time: 16.633
-  exp_frame_time: 16.702
-  exp_frame_time: 16.772
-  exp_frame_time: 16.709
-  exp_frame_time: 16.841
-  exp_frame_time: 16.556
-  exp_frame_time: 16.703
-  exp_frame_time: 16.7
-  exp_frame_time: 16.702
-  exp_frame_time: 16.71
-  exp_frame_time: 16.748
-  exp_frame_time: 16.652
-  exp_frame_time: 16.722
-  exp_frame_time: 16.686
-  exp_frame_time: 16.697
-  exp_frame_time: 16.691
-  exp_frame_time: 16.691
-  exp_frame_time: 16.709
-  exp_frame_time: 16.698
-  exp_frame_time: 16.703
-  exp_frame_time: 16.714
-  exp_frame_time: 16.861
-  exp_frame_time: 16.535
-  exp_frame_time: 16.737
-  exp_frame_time: 16.671
-  exp_frame_time: 16.693
-  exp_frame_time: 16.701
-  exp_frame_time: 16.614
-  exp_frame_time: 16.711
-  exp_frame_time: 16.77
-  exp_frame_time: 16.632
-  exp_frame_time: 16.689
-  exp_frame_time: 16.789
-  exp_frame_time: 16.711
-  exp_frame_time: 16.689
-  exp_frame_time: 16.696
-  exp_frame_time: 16.699
-  exp_frame_time: 16.699
-  exp_frame_time: 16.686
-  exp_frame_time: 16.64
-  exp_frame_time: 16.701
-  exp_frame_time: 16.794
-  exp_frame_time: 16.704
-  exp_frame_time: 16.714
-  exp_frame_time: 16.728
-  exp_frame_time: 16.664
-  exp_frame_time: 16.71
-  exp_frame_time: 16.631
-  exp_frame_time: 16.781
-  exp_frame_time: 16.628
-  exp_frame_time: 16.703
-  exp_frame_time: 16.773
-  exp_frame_time: 16.712
-  exp_frame_time: 16.699
-  exp_frame_time: 16.707
-  exp_frame_time: 16.704
-  exp_frame_time: 16.64
-  exp_frame_time: 16.702
-  exp_frame_time: 16.705
-  exp_frame_time: 16.809
-  exp_frame_time: 16.671
-  exp_frame_time: 16.614
-  exp_frame_time: 16.721
-  exp_frame_time: 16.701
-  exp_frame_time: 16.701
-  exp_frame_time: 16.776
-  exp_frame_time: 16.63
-  exp_frame_time: 16.787
-  exp_frame_time: 16.623
-  exp_frame_time: 16.707
-  avg_surface_fps: 59.86008821173197
-  exp_avg_surface_fps: 59.861591661151287
-}
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/frame_times_metric_test.sql b/base/tracing/test/trace_processor/diff_tests/chrome/frame_times_metric_test.sql
deleted file mode 100644
index 03ed7169..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/frame_times_metric_test.sql
+++ /dev/null
@@ -1,7 +0,0 @@
--- Copyright 2023 The Chromium Authors
--- Use of this source code is governed by a BSD-style license that can be
--- found in the LICENSE file.
-
-SELECT RUN_METRIC('experimental/frame_times.sql');
-
-SELECT * FROM AvgSurfaceFps;
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/long_event_latency.textproto b/base/tracing/test/trace_processor/diff_tests/chrome/long_event_latency.textproto
deleted file mode 100644
index 10635a98..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/long_event_latency.textproto
+++ /dev/null
@@ -1,212 +0,0 @@
-# Long latency events from two renderer processes
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 10
-    process {
-      pid: 1001
-      process_name: "Renderer"
-    }
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 20
-    process {
-      pid: 1002
-      process_name: "Renderer"
-    }
-  }
-}
-
-# EventLatency 1: 200ms duration
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 101
-    parent_uuid: 10
-    name: "EventLatency"
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 111000
-  track_event {
-    track_uuid: 101
-    categories: "cat"
-    debug_annotations: {
-      name: "event"
-      string_value: "FirstGestureScrollUpdate"
-    }
-    name: "EventLatency"
-    type: 1
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 200111000
-  track_event {
-    track_uuid: 101
-    categories: "cat"
-    name: "EventLatency"
-    type: 2
-  }
-}
-
-# EventLatency 2: 110ms ending at the same timestamp as EventLatency 1.
-# EventLatency 1 and 2 are reported as one occurrence of long latency.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 102
-    parent_uuid: 10
-    name: "EventLatency"
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 90111000
-  track_event {
-    track_uuid: 102
-    categories: "cat"
-    debug_annotations: {
-      name: "event"
-      string_value: "GestureScrollUpdate"
-    }
-    name: "EventLatency"
-    type: 1
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 200111000
-  track_event {
-    track_uuid: 102
-    categories: "cat"
-    name: "EventLatency"
-    type: 2
-  }
-}
-
-# EventLatency 3: a long latency slightly above the 100ms threshold
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 103
-    parent_uuid: 10
-    name: "EventLatency"
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 180111000
-  track_event {
-    track_uuid: 103
-    categories: "cat"
-    debug_annotations: {
-      name: "event"
-      string_value: "GestureScrollUpdate"
-    }
-    name: "EventLatency"
-    type: 1
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 280111001
-  track_event {
-    track_uuid: 103
-    categories: "cat"
-    name: "EventLatency"
-    type: 2
-  }
-}
-
-# EventLatency 4: below the 100ms threshold; not a long latency
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 104
-    parent_uuid: 10
-    name: "EventLatency"
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 250111001
-  track_event {
-    track_uuid: 104
-    categories: "cat"
-    debug_annotations: {
-      name: "event"
-      string_value: "GestureScrollUpdate"
-    }
-    name: "EventLatency"
-    type: 1
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 350111000
-  track_event {
-    track_uuid: 104
-    categories: "cat"
-    name: "EventLatency"
-    type: 2
-  }
-}
-
-# EventLatency 5: long latency from the second renderer process;
-# should be reported as a standalone long latency occurrence despite having
-# the same end time as EventLatency 1.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 201
-    parent_uuid: 20
-    name: "EventLatency"
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 111000
-  track_event {
-    track_uuid: 201
-    categories: "cat"
-    debug_annotations: {
-      name: "event"
-      string_value: "GestureScrollUpdate"
-    }
-    name: "EventLatency"
-    type: 1
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 200111000
-  track_event {
-    track_uuid: 201
-    categories: "cat"
-    name: "EventLatency"
-    type: 2
-  }
-}
\ No newline at end of file
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/long_task_tracking_trace_chrome_long_tasks_delaying_input_processing_compare_default_test.out b/base/tracing/test/trace_processor/diff_tests/chrome/long_task_tracking_trace_chrome_long_tasks_delaying_input_processing_compare_default_test.out
deleted file mode 100644
index 9f3f1f6..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/long_task_tracking_trace_chrome_long_tasks_delaying_input_processing_compare_default_test.out
+++ /dev/null
@@ -1,16 +0,0 @@
-
-"full_name","duration_ms","slice_id"
-"cc.mojom.RenderFrameMetadataObserverClient message (hash=330497194)",4.054000,5054
-"FrameHost::BeginNavigation (unknown frame type)",9.647000,15011
-"FrameHost::BeginNavigation (unknown frame type)",12.937000,15448
-"network.mojom.NetworkService reply (hash=1419877769)",14.115000,15900
-"content.mojom.NavigationClient reply (hash=479951742)",4.935000,21525
-"RunTask(posted_from=cc/trees/single_thread_proxy.cc:DidReceiveCompositorFrameAckOnImplThread)",4.292000,42834
-"content.mojom.FrameHost message (hash=2324894379)",4.038000,70576
-"FrameHost::BeginNavigation (unknown frame type)",15.509000,70929
-"cc.mojom.RenderFrameMetadataObserverClient message (hash=330497194)",4.940000,89185
-"content.mojom.NavigationClient reply (hash=479951742)",5.413000,91211
-"FrameHost::BeginNavigation (unknown frame type)",10.327000,98059
-"content.mojom.NavigationRendererCancellationListener message (hash=281273569)",7.873000,99939
-"FrameHost::BeginNavigation (unknown frame type)",9.579000,124733
-"network.mojom.NetworkService reply (hash=1419877769)",10.132000,126133
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/long_task_tracking_trace_chrome_long_tasks_delaying_input_processing_test.out b/base/tracing/test/trace_processor/diff_tests/chrome/long_task_tracking_trace_chrome_long_tasks_delaying_input_processing_test.out
deleted file mode 100644
index 79b50361..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/long_task_tracking_trace_chrome_long_tasks_delaying_input_processing_test.out
+++ /dev/null
@@ -1,16 +0,0 @@
-
-"full_name","duration_ms","slice_id"
-"cc.mojom.RenderFrameMetadataObserverClient message (hash=330497194)",4.061000,5055
-"FrameHost::BeginNavigation (unknown frame type)",9.651000,15012
-"FrameHost::BeginNavigation (unknown frame type)",12.943000,15449
-"network.mojom.NetworkService reply (hash=1419877769)",14.118000,15899
-"content.mojom.NavigationClient reply (hash=479951742)",4.937000,21526
-"RunTask(posted_from=cc/trees/single_thread_proxy.cc:DidReceiveCompositorFrameAckOnImplThread)",4.298000,42835
-"content.mojom.FrameHost message (hash=2324894379)",4.046000,70575
-"FrameHost::BeginNavigation (unknown frame type)",15.514000,70930
-"cc.mojom.RenderFrameMetadataObserverClient message (hash=330497194)",4.950000,89184
-"content.mojom.NavigationClient reply (hash=479951742)",5.418000,91212
-"FrameHost::BeginNavigation (unknown frame type)",10.333000,98058
-"content.mojom.NavigationRendererCancellationListener message (hash=281273569)",7.876000,99938
-"FrameHost::BeginNavigation (unknown frame type)",9.585000,124732
-"network.mojom.NetworkService reply (hash=1419877769)",10.134000,126134
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_chrome_dump_events.out b/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_chrome_dump_events.out
deleted file mode 100644
index aea49aa..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_chrome_dump_events.out
+++ /dev/null
@@ -1,19 +0,0 @@
-"process_snapshot_id","upid","snapshot_id","timestamp","detail_level"
-0,1,0,111027205123000,"detailed"
-1,2,0,111027205123000,"detailed"
-2,3,0,111027205123000,"detailed"
-3,5,0,111027205123000,"detailed"
-4,4,0,111027205123000,"detailed"
-5,8,0,111027205123000,"detailed"
-6,6,0,111027205123000,"detailed"
-7,7,0,111027205123000,"detailed"
-8,0,0,111027205123000,"detailed"
-9,1,1,111037187565000,"detailed"
-10,2,1,111037187565000,"detailed"
-11,3,1,111037187565000,"detailed"
-12,5,1,111037187565000,"detailed"
-13,4,1,111037187565000,"detailed"
-14,8,1,111037187565000,"detailed"
-15,6,1,111037187565000,"detailed"
-16,7,1,111037187565000,"detailed"
-17,0,1,111037187565000,"detailed"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_edges.out b/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_edges.out
deleted file mode 100644
index 15bb371..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_edges.out
+++ /dev/null
@@ -1,21 +0,0 @@
-"id","source_node_id","target_node_id","importance"
-0,1734,1863,0
-1,1728,1839,0
-2,1732,1772,0
-3,1729,1786,0
-4,1730,1805,0
-5,1735,1859,0
-6,1733,1844,0
-7,1727,1840,0
-8,1731,1850,0
-9,1726,1849,0
-10,1636,1639,0
-11,1681,1846,0
-12,1683,1744,0
-13,1680,1849,0
-14,1682,1859,0
-15,1707,1621,0
-16,1634,1638,0
-17,1399,1193,0
-18,1083,1795,2
-19,1358,1846,0
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_general_validation.out b/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_general_validation.out
deleted file mode 100644
index cb203ee..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_general_validation.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"total_snapshots","total_processes","total_process_snapshots","total_nodes","total_edges","total_node_args","total_smaps"
-2,9,18,3584,788,5014,33979
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_node_args.out b/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_node_args.out
deleted file mode 100644
index c6adffe..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_node_args.out
+++ /dev/null
@@ -1,21 +0,0 @@
-"node_id","key","value_type","int_value","string_value"
-20,"id.value","string","[NULL]","C7BC3FD59A40689345EB9CB08570641B"
-20,"locked_size.value","int",0,"[NULL]"
-20,"locked_size.unit","string","[NULL]","bytes"
-20,"virtual_size.value","int",961,"[NULL]"
-20,"virtual_size.unit","string","[NULL]","bytes"
-21,"id.value","string","[NULL]","AF621E3BE175B9B618BAADF9138E5598"
-21,"locked_size.value","int",0,"[NULL]"
-21,"locked_size.unit","string","[NULL]","bytes"
-21,"virtual_size.value","int",529,"[NULL]"
-21,"virtual_size.unit","string","[NULL]","bytes"
-30,"free_size.value","int",1048576,"[NULL]"
-30,"free_size.unit","string","[NULL]","bytes"
-32,"free_size.value","int",65472,"[NULL]"
-32,"free_size.unit","string","[NULL]","bytes"
-54,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/Site Characteristics Database"
-57,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/Sync Data/LevelDB"
-60,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/shared_proto_db/metadata"
-63,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/GCM Store/Encryption"
-66,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/Service Worker/Database"
-69,"name.value","string","[NULL]","/home/toki/.config/chromium/Default/Extension Rules"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_nodes.out b/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_nodes.out
deleted file mode 100644
index 39a8108..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_nodes.out
+++ /dev/null
@@ -1,21 +0,0 @@
-"id","process_snapshot_id","parent_node_id","path","size","effective_size"
-0,0,"[NULL]","cc",2899968,2899968
-1,0,0,"cc/tile_memory",2899968,2899968
-2,0,1,"cc/tile_memory/provider_0",2899968,2899968
-3,0,2,"cc/tile_memory/provider_0/resource_10",262144,262144
-4,0,2,"cc/tile_memory/provider_0/resource_11",131072,131072
-5,0,2,"cc/tile_memory/provider_0/resource_14",262144,262144
-6,0,2,"cc/tile_memory/provider_0/resource_15",131072,131072
-7,0,2,"cc/tile_memory/provider_0/resource_21",262144,262144
-8,0,2,"cc/tile_memory/provider_0/resource_23",262144,262144
-9,0,2,"cc/tile_memory/provider_0/resource_26",131072,131072
-10,0,2,"cc/tile_memory/provider_0/resource_3",262144,262144
-11,0,2,"cc/tile_memory/provider_0/resource_31",131072,131072
-12,0,2,"cc/tile_memory/provider_0/resource_36",262144,262144
-13,0,2,"cc/tile_memory/provider_0/resource_4",131072,131072
-14,0,2,"cc/tile_memory/provider_0/resource_41",16384,16384
-15,0,2,"cc/tile_memory/provider_0/resource_42",262144,262144
-16,0,2,"cc/tile_memory/provider_0/resource_7",262144,262144
-17,0,2,"cc/tile_memory/provider_0/resource_8",131072,131072
-18,0,"[NULL]","discardable",16384,16384
-19,0,18,"discardable/process_ffffffff",16384,16384
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_os_dump_events.out b/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_os_dump_events.out
deleted file mode 100644
index f1ce018..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_os_dump_events.out
+++ /dev/null
@@ -1,19 +0,0 @@
-"upid","pid","name","timestamp","detail_level","private_footprint_kb","peak_resident_set_kb","is_peak_rss_resettable"
-0,0,"[NULL]",111027205123000,"detailed","[NULL]","[NULL]","[NULL]"
-1,29694,"Browser",111027205123000,"detailed",76656640.000000,479354880.000000,1
-2,29725,"GPU Process",111027205123000,"detailed",62836736.000000,280952832.000000,1
-3,29728,"Service: network.mojom.NetworkService",111027205123000,"detailed",35360768.000000,229261312.000000,1
-4,29764,"Service: data_decoder.mojom.DataDecoderService",111027205123000,"detailed",30576640.000000,201347072.000000,1
-5,29737,"Service: storage.mojom.StorageService",111027205123000,"detailed",30617600.000000,207138816.000000,1
-6,29833,"Renderer",111027205123000,"detailed",36802560.000000,264036352.000000,1
-7,29877,"Service: tracing.mojom.TracingService",111027205123000,"detailed",31002624.000000,199208960.000000,1
-8,29807,"Renderer",111027205123000,"detailed",87248896.000000,451424256.000000,1
-0,0,"[NULL]",111037187565000,"detailed","[NULL]","[NULL]","[NULL]"
-1,29694,"Browser",111037187565000,"detailed",85942272.000000,491671552.000000,1
-2,29725,"GPU Process",111037187565000,"detailed",62754816.000000,275906560.000000,1
-3,29728,"Service: network.mojom.NetworkService",111037187565000,"detailed",35495936.000000,229351424.000000,1
-4,29764,"Service: data_decoder.mojom.DataDecoderService",111037187565000,"detailed",30679040.000000,201424896.000000,1
-5,29737,"Service: storage.mojom.StorageService",111037187565000,"detailed",30650368.000000,205791232.000000,1
-6,29833,"Renderer",111037187565000,"detailed",36950016.000000,264843264.000000,1
-7,29877,"Service: tracing.mojom.TracingService",111037187565000,"detailed",33386496.000000,204554240.000000,1
-8,29807,"Renderer",111037187565000,"detailed",76832768.000000,445292544.000000,1
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_os_dump_events_test.sql b/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_os_dump_events_test.sql
deleted file mode 100644
index 4a18b369..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_os_dump_events_test.sql
+++ /dev/null
@@ -1,45 +0,0 @@
---
--- Copyright 2020 The Android Open Source Project
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
---     https://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an "AS IS" BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
---
-
-SELECT
-  p.upid,
-  pid,
-  p.name,
-  timestamp,
-  detail_level,
-  pf.value AS private_footprint_kb,
-  prs.value AS peak_resident_set_kb,
-  EXTRACT_ARG(p.arg_set_id, 'is_peak_rss_resettable')
-    AS is_peak_rss_resettable
-FROM process p
-LEFT JOIN memory_snapshot
-LEFT JOIN (
-  SELECT id, upid
-  FROM process_counter_track
-  WHERE name = 'chrome.private_footprint_kb'
-  ) AS pct_pf
-  ON p.upid = pct_pf.upid
-LEFT JOIN counter pf 
-  ON timestamp = pf.ts AND pct_pf.id = pf.track_id
-LEFT JOIN (
-  SELECT id, upid
-  FROM process_counter_track
-  WHERE name = 'chrome.peak_resident_set_kb'
-  ) AS pct_prs
-  ON p.upid = pct_prs.upid
-LEFT JOIN counter prs 
-  ON timestamp = prs.ts AND pct_prs.id = prs.track_id
-ORDER BY timestamp;
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_smaps.out b/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_smaps.out
deleted file mode 100644
index 255526d..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/memory_snapshot_smaps.out
+++ /dev/null
@@ -1,21 +0,0 @@
-"upid","name","ts","path","size_kb","private_dirty_kb","swap_kb","file_name","start_address","module_timestamp","module_debugid","module_debug_path","protection_flags","private_clean_resident_kb","shared_dirty_resident_kb","shared_clean_resident_kb","locked_kb","proportional_resident_kb"
-1,"Browser",111027205123000,"[NULL]",4,0,0,"",14051238432768,0,"[NULL]","[NULL]",0,0,0,0,0,0
-1,"Browser",111027205123000,"[NULL]",40956,40464,0,"",14051238436864,0,"[NULL]","[NULL]",6,0,0,0,0,40464
-1,"Browser",111027205123000,"[NULL]",4,0,0,"",14051280375808,0,"[NULL]","[NULL]",0,0,0,0,0,0
-1,"Browser",111027205123000,"[NULL]",11860,8620,0,"",14051280379904,0,"[NULL]","[NULL]",6,0,0,0,0,8620
-1,"Browser",111027205123000,"[NULL]",67896,4,0,"/home/toki/chromium/src/out/Default/chrome",94168098267136,0,"[NULL]","[NULL]",4,6824,0,14812,0,8788
-1,"Browser",111027205123000,"[NULL]",123784,4,0,"/home/toki/chromium/src/out/Default/chrome",94168167792640,0,"[NULL]","[NULL]",5,62584,0,28044,0,70896
-1,"Browser",111027205123000,"[NULL]",3036,3036,0,"/home/toki/chromium/src/out/Default/chrome",94168294547456,0,"[NULL]","[NULL]",4,0,0,0,0,3036
-1,"Browser",111027205123000,"[NULL]",148,136,0,"/home/toki/chromium/src/out/Default/chrome",94168297656320,0,"[NULL]","[NULL]",6,0,0,12,0,137
-1,"Browser",111027205123000,"[NULL]",404,240,0,"",94168297807872,0,"[NULL]","[NULL]",6,0,0,0,0,240
-1,"Browser",111027205123000,"[NULL]",2048,0,0,"/dev/shm/.org.chromium.Chromium.Doo3XC (deleted)",140632555954176,0,"[NULL]","[NULL]",134,0,4,0,0,2
-1,"Browser",111027205123000,"[NULL]",2048,0,0,"/dev/shm/.org.chromium.Chromium.PxFFQm (deleted)",140632558575616,0,"[NULL]","[NULL]",134,0,4,0,0,2
-1,"Browser",111027205123000,"[NULL]",428,0,0,"/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so",140632563163136,0,"[NULL]","[NULL]",5,128,0,136,0,196
-1,"Browser",111027205123000,"[NULL]",2044,0,0,"/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so",140632563601408,0,"[NULL]","[NULL]",0,0,0,0,0,0
-1,"Browser",111027205123000,"[NULL]",68,68,0,"/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so",140632565694464,0,"[NULL]","[NULL]",4,0,0,0,0,68
-1,"Browser",111027205123000,"[NULL]",40,40,0,"/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so",140632565764096,0,"[NULL]","[NULL]",6,0,0,0,0,40
-1,"Browser",111027205123000,"[NULL]",668,0,0,"/usr/lib/x86_64-linux-gnu/nss/libfreeblpriv3.so",140632565805056,0,"[NULL]","[NULL]",5,340,0,16,0,344
-1,"Browser",111027205123000,"[NULL]",2048,0,0,"/usr/lib/x86_64-linux-gnu/nss/libfreeblpriv3.so",140632566489088,0,"[NULL]","[NULL]",0,0,0,0,0,0
-1,"Browser",111027205123000,"[NULL]",8,8,0,"/usr/lib/x86_64-linux-gnu/nss/libfreeblpriv3.so",140632568586240,0,"[NULL]","[NULL]",4,0,0,0,0,8
-1,"Browser",111027205123000,"[NULL]",4,4,0,"/usr/lib/x86_64-linux-gnu/nss/libfreeblpriv3.so",140632568594432,0,"[NULL]","[NULL]",6,0,0,0,0,4
-1,"Browser",111027205123000,"[NULL]",16,16,0,"",140632568598528,0,"[NULL]","[NULL]",6,0,0,0,0,16
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes.py b/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes.py
deleted file mode 100755
index 42de8ff..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from os import sys
-
-import synth_common
-from synth_common import s_to_ns
-
-trace = synth_common.create_trace()
-
-trace.add_chrome_metadata(os_name="Android")
-
-track1 = 1234
-track2 = 4567
-gpu_track = 7890
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(track2, pid=2)
-trace.add_process_track_descriptor(gpu_track, pid=4)
-
-frame_period = s_to_ns(1.0 / 60)
-
-trace.add_track_event_slice("VSync", ts=s_to_ns(3), dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period, dur=10, track=gpu_track)
-# Frame skipped, but modified rail mode won't go back to foreground_idle
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 3, dur=10, track=gpu_track)
-# Larger gap now when mode will go to foreground_idle
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 12, dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 13, dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 14, dur=10, track=gpu_track)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3),
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2.5),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(2.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_extra_long.py b/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_extra_long.py
deleted file mode 100755
index f56fbcd..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_extra_long.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from os import sys
-
-import synth_common
-from synth_common import s_to_ns
-
-trace = synth_common.create_trace()
-
-trace.add_chrome_metadata(os_name="Android")
-
-track1 = 1234
-gpu_track = 7890
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(gpu_track, pid=4)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-# ceased to ensure that the RAIL mode is extended to the end of the process
-# rather than the end of the trace itself.
-# Generate an extra long trace event making the trace longer than 10 minutes
-# causing the trace to be completely excluded.
-trace.add_track_event_slice("VSync", ts=s_to_ns(1000), dur=10, track=gpu_track)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_long.py b/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_long.py
deleted file mode 100755
index 7ec07a6a..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_long.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from os import sys
-
-import synth_common
-from synth_common import s_to_ns
-
-trace = synth_common.create_trace()
-
-trace.add_chrome_metadata(os_name="Android")
-
-track1 = 1234
-gpu_track = 7890
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(gpu_track, pid=4)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-# Generate an extra trace event long after events on the renderer process have
-# ceased to ensure that the RAIL mode is extended to the end of the process
-# rather than the end of the trace itself.
-trace.add_track_event_slice("VSync", ts=s_to_ns(25), dur=10, track=gpu_track)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_no_vsyncs.py b/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_no_vsyncs.py
deleted file mode 100755
index 8a9be676..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_no_vsyncs.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from os import sys
-
-import synth_common
-from synth_common import s_to_ns
-
-trace = synth_common.create_trace()
-
-trace.add_chrome_metadata(os_name="Android")
-
-track1 = 1234
-track2 = 4567
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(track2, pid=2)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3),
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2.5),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(2.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_with_input.py b/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_with_input.py
deleted file mode 100755
index e1e6b99..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/modified_rail_modes_with_input.py
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from os import sys
-
-import synth_common
-from synth_common import s_to_ns
-
-trace = synth_common.create_trace()
-
-trace.add_chrome_metadata(os_name="Android")
-
-track1 = 1234
-track2 = 4567
-gpu_track = 7890
-
-trace.add_process_track_descriptor(track1, pid=0)
-trace.add_process_track_descriptor(track2, pid=2)
-trace.add_process_track_descriptor(gpu_track, pid=4)
-
-frame_period = s_to_ns(1.0 / 60)
-
-trace.add_track_event_slice("VSync", ts=s_to_ns(3), dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period, dur=10, track=gpu_track)
-# Frame skipped, but modified rail mode won't go back to foreground_idle
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 3, dur=10, track=gpu_track)
-# Larger gap now when mode will go to foreground_idle
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 12, dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 13, dur=10, track=gpu_track)
-trace.add_track_event_slice(
-    "VSync", ts=s_to_ns(3) + frame_period * 14, dur=10, track=gpu_track)
-
-trace.add_track_event_slice(
-    "InputLatency::GestureScrollBegin", ts=s_to_ns(3), dur=10)
-trace.add_track_event_slice(
-    "InputLatency::GestureScrollEnd", ts=s_to_ns(3) + frame_period * 4, dur=10)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_RESPONSE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2),
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_LOAD)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3),
-    dur=-1,
-    track=track1,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-trace.add_rail_mode_slice(
-    ts=0,
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(1),
-    dur=s_to_ns(2.5),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(2.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_ANIMATION)
-trace.add_rail_mode_slice(
-    ts=s_to_ns(3.5),
-    dur=s_to_ns(1),
-    track=track2,
-    mode=trace.prototypes.ChromeRAILMode.RAIL_MODE_IDLE)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/proto_content.out b/base/tracing/test/trace_processor/diff_tests/chrome/proto_content.out
deleted file mode 100644
index 6c37864..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/proto_content.out
+++ /dev/null
@@ -1,11 +0,0 @@
-"path","total_size"
-"TracePacket",364932
-"TracePacket.#track_event.TrackEvent",254590
-"TracePacket.#trusted_uid.int32",95260
-"TracePacket.#track_event.TrackEvent.#debug_annotations.DebugAnnotation.#string_value.string",73911
-"TracePacket.#timestamp.uint64",66933
-"TracePacket.#trusted_packet_sequence_id.uint32",39091
-"TracePacket.#sequence_flags.uint32",39020
-"TracePacket.#track_event.TrackEvent.#extra_counter_values.int64",36079
-"TracePacket.#track_event.TrackEvent.#chrome_latency_info.ChromeLatencyInfo",33452
-"TracePacket.#track_event.TrackEvent.#type.enum",32937
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/proto_content_path_test.sql b/base/tracing/test/trace_processor/diff_tests/chrome/proto_content_path_test.sql
deleted file mode 100644
index f2a3ab0..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/proto_content_path_test.sql
+++ /dev/null
@@ -1,12 +0,0 @@
--- Copyright 2023 The Chromium Authors
--- Use of this source code is governed by a BSD-style license that can be
--- found in the LICENSE file.
-
-SELECT content.total_size,
-  frame.field_type, frame.field_name,
-  frame.parent_id,
-  EXTRACT_ARG(frame.arg_set_id, 'event.category') AS event_category,
-  EXTRACT_ARG(frame.arg_set_id, 'event.name') AS event_name
-FROM experimental_proto_path AS frame JOIN experimental_proto_content AS content ON content.path_id = frame.id
-ORDER BY total_size DESC, path
-LIMIT 10;
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/proto_content_test.sql b/base/tracing/test/trace_processor/diff_tests/chrome/proto_content_test.sql
deleted file mode 100644
index 77fd5286..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/proto_content_test.sql
+++ /dev/null
@@ -1,9 +0,0 @@
--- Copyright 2023 The Chromium Authors
--- Use of this source code is governed by a BSD-style license that can be
--- found in the LICENSE file.
-
-SELECT path, SUM(total_size) as total_size
-FROM experimental_proto_content as content JOIN experimental_proto_path as frame ON content.path_id = frame.id
-GROUP BY path
-ORDER BY total_size DESC, path
-LIMIT 10;
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event.out b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event.out
deleted file mode 100644
index 148f46b2..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event.out
+++ /dev/null
@@ -1,1114 +0,0 @@
-
-"trace_id","ts","dur","jank","step","ancestor_end","maybe_next_ancestor_ts","next_ts","next_trace_id","next_step"
-2709,544958000403,19009426,0,"AsyncBegin",544958000403,544959793403,544960259403,2709,"Begin"
-2709,544960259403,2000,0,"Begin",544960452403,544959793403,544960408403,2709,"STEP_SEND_INPUT_EVENT_UI"
-2709,544960408403,33000,0,"STEP_SEND_INPUT_EVENT_UI",544960452403,544960696611,544960702611,2709,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2709,544960702611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",544960714611,544965468611,544965475611,2709,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2709,544965475611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",544965507611,544966414611,544966414611,2709,"STEP_SWAP_BUFFERS"
-2709,544966414611,1000,0,"STEP_SWAP_BUFFERS",544966415611,544967888829,544967888829,2709,"STEP_DRAW_AND_SWAP"
-2709,544967888829,2000,0,"STEP_DRAW_AND_SWAP",544967890829,544977012829,544977012829,2709,"End"
-2709,544977012829,1000,0,"End",544977013829,"[NULL]",544966000403,2711,"AsyncBegin"
-2711,544966000403,22609426,0,"AsyncBegin",544966000403,544967825403,544967961403,2711,"Begin"
-2711,544967961403,2000,0,"Begin",544968036403,544967825403,544967991403,2711,"STEP_SEND_INPUT_EVENT_UI"
-2711,544967991403,33000,0,"STEP_SEND_INPUT_EVENT_UI",544968036403,544968345611,544968348611,2711,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2711,544968348611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",544968359611,544976665611,544976668611,2711,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2711,544976668611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",544976702611,544977398611,544977398611,2711,"STEP_SWAP_BUFFERS"
-2711,544977398611,5000,0,"STEP_SWAP_BUFFERS",544977403611,544978840829,544978840829,2711,"STEP_DRAW_AND_SWAP"
-2711,544978840829,8000,0,"STEP_DRAW_AND_SWAP",544978848829,544988619829,544988619829,2711,"End"
-2711,544988619829,2000,0,"End",544988621829,"[NULL]",544983000403,2715,"AsyncBegin"
-2715,544983000403,28089426,0,"AsyncBegin",544983000403,544984070403,544984265403,2715,"Begin"
-2715,544984265403,2000,0,"Begin",544984392403,544984070403,544984299403,2715,"STEP_SEND_INPUT_EVENT_UI"
-2715,544984299403,39000,0,"STEP_SEND_INPUT_EVENT_UI",544984392403,544984409611,544984412611,2715,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2715,544984412611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",544984423611,544988228611,544988232611,2715,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2715,544988232611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",544988268611,544989548611,544989548611,2715,"STEP_SWAP_BUFFERS"
-2715,544989548611,6000,0,"STEP_SWAP_BUFFERS",544989554611,545001087829,545001087829,2715,"STEP_DRAW_AND_SWAP"
-2715,545001087829,8000,0,"STEP_DRAW_AND_SWAP",545001095829,545011097829,545011097829,2715,"End"
-2715,545011097829,2000,0,"End",545011099829,"[NULL]",544991000403,2717,"AsyncBegin"
-2717,544991000403,30714426,0,"AsyncBegin",544991000403,544992452403,544992612403,2717,"Begin"
-2717,544992612403,2000,0,"Begin",544992695403,544992452403,544992644403,2717,"STEP_SEND_INPUT_EVENT_UI"
-2717,544992644403,36000,0,"STEP_SEND_INPUT_EVENT_UI",544992695403,544992755611,544992757611,2717,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2717,544992757611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",544992767611,544999304611,544999309611,2717,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2717,544999309611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",544999349611,545000565611,545000565611,2717,"STEP_SWAP_BUFFERS"
-2717,545000565611,7000,0,"STEP_SWAP_BUFFERS",545000572611,545011641829,545011641829,2717,"STEP_DRAW_AND_SWAP"
-2717,545011641829,5000,0,"STEP_DRAW_AND_SWAP",545011646829,545021756829,545021756829,2717,"End"
-2717,545021756829,9000,0,"End",545021765829,"[NULL]",544999000403,2719,"AsyncBegin"
-2719,544999000403,34740426,0,"AsyncBegin",544999000403,545000581403,545000721403,2719,"Begin"
-2719,545000721403,1000,0,"Begin",545000923403,545000581403,545000748403,2719,"STEP_SEND_INPUT_EVENT_UI"
-2719,545000748403,34000,0,"STEP_SEND_INPUT_EVENT_UI",545000923403,545000825611,545000827611,2719,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2719,545000827611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545000836611,545010457611,545010461611,2719,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2719,545010461611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545010555611,545011228611,545011228611,2719,"STEP_SWAP_BUFFERS"
-2719,545011228611,7000,0,"STEP_SWAP_BUFFERS",545011235611,545023105829,545023105829,2719,"STEP_DRAW_AND_SWAP"
-2719,545023105829,8000,0,"STEP_DRAW_AND_SWAP",545023113829,545033749829,545033749829,2719,"End"
-2719,545033749829,2000,0,"End",545033751829,"[NULL]",545007000403,2721,"AsyncBegin"
-2721,545007000403,37462426,0,"AsyncBegin",545007000403,545010006403,545010187403,2721,"Begin"
-2721,545010187403,1000,0,"Begin",545010323403,545010006403,545010267403,2721,"STEP_SEND_INPUT_EVENT_UI"
-2721,545010267403,41000,0,"STEP_SEND_INPUT_EVENT_UI",545010323403,545010685611,545010687611,2721,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2721,545010687611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545010695611,545021699611,545021703611,2721,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2721,545021703611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545021748611,545022454611,545022454611,2721,"STEP_SWAP_BUFFERS"
-2721,545022454611,5000,0,"STEP_SWAP_BUFFERS",545022459611,545034641829,545034641829,2721,"STEP_DRAW_AND_SWAP"
-2721,545034641829,5000,0,"STEP_DRAW_AND_SWAP",545034646829,545044471829,545044471829,2721,"End"
-2721,545044471829,3000,0,"End",545044474829,"[NULL]",545024000403,2725,"AsyncBegin"
-2725,545024000403,31889426,0,"AsyncBegin",545024000403,545025279403,545025586403,2725,"Begin"
-2725,545025586403,2000,0,"Begin",545025746403,545025279403,545025615403,2725,"STEP_SEND_INPUT_EVENT_UI"
-2725,545025615403,117000,0,"STEP_SEND_INPUT_EVENT_UI",545025746403,545025698611,545025703611,2725,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2725,545025703611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545025713611,545033251611,545033256611,2725,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2725,545033256611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545033344611,545034007611,545034007611,2725,"STEP_SWAP_BUFFERS"
-2725,545034007611,5000,0,"STEP_SWAP_BUFFERS",545034012611,545047703829,545047703829,2725,"STEP_DRAW_AND_SWAP"
-2725,545047703829,1000,0,"STEP_DRAW_AND_SWAP",545047704829,545055892829,545055892829,2725,"End"
-2725,545055892829,1000,0,"End",545055893829,"[NULL]",545032000403,2727,"AsyncBegin"
-2727,545032000403,23876426,0,"AsyncBegin",545032000403,545033878403,545034017403,2727,"Begin"
-2727,545034017403,1000,0,"Begin",545034128403,545033878403,545034048403,2727,"STEP_SEND_INPUT_EVENT_UI"
-2727,545034048403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545034128403,545034224611,545034228611,2727,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2727,545034228611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545034237611,545044106611,545044111611,2727,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2727,545044111611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545044160611,545046053611,545046053611,2727,"STEP_SWAP_BUFFERS"
-2727,545046053611,8000,0,"STEP_SWAP_BUFFERS",545046061611,545047694829,545047694829,2727,"STEP_DRAW_AND_SWAP"
-2727,545047694829,7000,0,"STEP_DRAW_AND_SWAP",545047701829,545055884829,545055884829,2727,"End"
-2727,545055884829,2000,0,"End",545055886829,"[NULL]",545040000403,2729,"AsyncBegin"
-2729,545040000403,28316426,0,"AsyncBegin",545040000403,545047588403,545047706403,2729,"Begin"
-2729,545047706403,2000,0,"Begin",545047774403,545047588403,545047731403,2729,"STEP_SEND_INPUT_EVENT_UI"
-2729,545047731403,31000,0,"STEP_SEND_INPUT_EVENT_UI",545047774403,545047812611,545047814611,2729,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2729,545047814611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545047825611,545055643611,545055671611,2729,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2729,545055671611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545055758611,545057874611,545057874611,2729,"STEP_SWAP_BUFFERS"
-2729,545057874611,10000,0,"STEP_SWAP_BUFFERS",545057884611,545059449829,545059449829,2729,"STEP_DRAW_AND_SWAP"
-2729,545059449829,9000,0,"STEP_DRAW_AND_SWAP",545059458829,545068323829,545068323829,2729,"End"
-2729,545068323829,2000,0,"End",545068325829,"[NULL]",545056000403,2733,"AsyncBegin"
-2733,545056000403,22620426,0,"AsyncBegin",545056000403,545059559403,545059690403,2733,"Begin"
-2733,545059690403,2000,0,"Begin",545059790403,545059559403,545059716403,2733,"STEP_SEND_INPUT_EVENT_UI"
-2733,545059716403,61000,0,"STEP_SEND_INPUT_EVENT_UI",545059790403,545059828611,545059831611,2733,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2733,545059831611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545059841611,545066118611,545066123611,2733,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2733,545066123611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545066163611,545068329611,545068329611,2733,"STEP_SWAP_BUFFERS"
-2733,545068329611,6000,0,"STEP_SWAP_BUFFERS",545068335611,545068802829,545068802829,2733,"STEP_DRAW_AND_SWAP"
-2733,545068802829,5000,0,"STEP_DRAW_AND_SWAP",545068807829,545078626829,545078626829,2733,"End"
-2733,545078626829,3000,0,"End",545078629829,"[NULL]",545065000403,2735,"AsyncBegin"
-2735,545065000403,23642426,0,"AsyncBegin",545065000403,545066840403,545067063403,2735,"Begin"
-2735,545067063403,3000,0,"Begin",545067143403,545066840403,545067095403,2735,"STEP_SEND_INPUT_EVENT_UI"
-2735,545067095403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545067143403,545067180611,545067186611,2735,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2735,545067186611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545067198611,545077803611,545077807611,2735,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2735,545077807611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545077844611,545079568611,545079568611,2735,"STEP_SWAP_BUFFERS"
-2735,545079568611,6000,0,"STEP_SWAP_BUFFERS",545079574611,545079993829,545079993829,2735,"STEP_DRAW_AND_SWAP"
-2735,545079993829,6000,0,"STEP_DRAW_AND_SWAP",545079999829,545088650829,545088650829,2735,"End"
-2735,545088650829,1000,0,"End",545088651829,"[NULL]",545081000403,2739,"AsyncBegin"
-2739,545081000403,19016426,0,"AsyncBegin",545081000403,545082897403,545083178403,2739,"Begin"
-2739,545083178403,1000,0,"Begin",545083448403,545082897403,545083322403,2739,"STEP_SEND_INPUT_EVENT_UI"
-2739,545083322403,113000,0,"STEP_SEND_INPUT_EVENT_UI",545083448403,545083401611,545083406611,2739,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2739,545083406611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545083416611,545088483611,545088487611,2739,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2739,545088487611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545088525611,545090577611,545090577611,2739,"STEP_SWAP_BUFFERS"
-2739,545090577611,7000,0,"STEP_SWAP_BUFFERS",545090584611,545091220829,545091220829,2739,"STEP_DRAW_AND_SWAP"
-2739,545091220829,6000,0,"STEP_DRAW_AND_SWAP",545091226829,545100025829,545100025829,2739,"End"
-2739,545100025829,2000,0,"End",545100027829,"[NULL]",545089000403,2741,"AsyncBegin"
-2741,545089000403,22491426,0,"AsyncBegin",545089000403,545090893403,545091180403,2741,"Begin"
-2741,545091180403,1000,0,"Begin",545091246403,545090893403,545091206403,2741,"STEP_SEND_INPUT_EVENT_UI"
-2741,545091206403,30000,0,"STEP_SEND_INPUT_EVENT_UI",545091246403,545091279611,545091284611,2741,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2741,545091284611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545091293611,545099726611,545099730611,2741,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2741,545099730611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545099774611,545101547611,545101547611,2741,"STEP_SWAP_BUFFERS"
-2741,545101547611,6000,0,"STEP_SWAP_BUFFERS",545101553611,545101957829,545101957829,2741,"STEP_DRAW_AND_SWAP"
-2741,545101957829,7000,0,"STEP_DRAW_AND_SWAP",545101964829,545111499829,545111499829,2741,"End"
-2741,545111499829,2000,0,"End",545111501829,"[NULL]",545098000403,2743,"AsyncBegin"
-2743,545098000403,24940426,0,"AsyncBegin",545098000403,545100311403,545100585403,2743,"Begin"
-2743,545100585403,1000,0,"Begin",545100658403,545100311403,545100613403,2743,"STEP_SEND_INPUT_EVENT_UI"
-2743,545100613403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545100658403,545100699611,545100704611,2743,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2743,545100704611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545100714611,545111157611,545111161611,2743,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2743,545111161611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545111274611,545113480611,545113480611,2743,"STEP_SWAP_BUFFERS"
-2743,545113480611,31000,0,"STEP_SWAP_BUFFERS",545113511611,545113945829,545113945829,2743,"STEP_DRAW_AND_SWAP"
-2743,545113945829,7000,0,"STEP_DRAW_AND_SWAP",545113952829,545122947829,545122947829,2743,"End"
-2743,545122947829,2000,0,"End",545122949829,"[NULL]",545114000403,2747,"AsyncBegin"
-2747,545114000403,19365426,0,"AsyncBegin",545114000403,545115387403,545115531403,2747,"Begin"
-2747,545115531403,1000,0,"Begin",545115601403,545115387403,545115557403,2747,"STEP_SEND_INPUT_EVENT_UI"
-2747,545115557403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545115601403,545115631611,545115633611,2747,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2747,545115633611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545115642611,545122513611,545122517611,2747,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2747,545122517611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545122556611,545124871611,545124871611,2747,"STEP_SWAP_BUFFERS"
-2747,545124871611,5000,0,"STEP_SWAP_BUFFERS",545124876611,545125297829,545125297829,2747,"STEP_DRAW_AND_SWAP"
-2747,545125297829,7000,0,"STEP_DRAW_AND_SWAP",545125304829,545133372829,545133372829,2747,"End"
-2747,545133372829,2000,0,"End",545133374829,"[NULL]",545122000403,2749,"AsyncBegin"
-2749,545122000403,22629426,0,"AsyncBegin",545122000403,545123889403,545124022403,2749,"Begin"
-2749,545124022403,1000,0,"Begin",545124095403,545123889403,545124047403,2749,"STEP_SEND_INPUT_EVENT_UI"
-2749,545124047403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545124095403,545124128611,545124131611,2749,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2749,545124131611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545124141611,545133176611,545133180611,2749,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2749,545133180611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545133220611,545135346611,545135346611,2749,"STEP_SWAP_BUFFERS"
-2749,545135346611,6000,0,"STEP_SWAP_BUFFERS",545135352611,545135871829,545135871829,2749,"STEP_DRAW_AND_SWAP"
-2749,545135871829,6000,0,"STEP_DRAW_AND_SWAP",545135877829,545144636829,545144636829,2749,"End"
-2749,545144636829,2000,0,"End",545144638829,"[NULL]",545139000403,2753,"AsyncBegin"
-2753,545139000403,17669426,0,"AsyncBegin",545139000403,545140415403,545140565403,2753,"Begin"
-2753,545140565403,1000,0,"Begin",545140662403,545140415403,545140591403,2753,"STEP_SEND_INPUT_EVENT_UI"
-2753,545140591403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545140662403,545140700611,545140702611,2753,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2753,545140702611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545140712611,545144685611,545144689611,2753,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2753,545144689611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545144727611,545146432611,545146432611,2753,"STEP_SWAP_BUFFERS"
-2753,545146432611,6000,0,"STEP_SWAP_BUFFERS",545146438611,545146884829,545146884829,2753,"STEP_DRAW_AND_SWAP"
-2753,545146884829,7000,0,"STEP_DRAW_AND_SWAP",545146891829,545156677829,545156677829,2753,"End"
-2753,545156677829,6000,0,"End",545156683829,"[NULL]",545147000403,2755,"AsyncBegin"
-2755,545147000403,20941426,0,"AsyncBegin",545147000403,545148122403,545148260403,2755,"Begin"
-2755,545148260403,1000,0,"Begin",545148331403,545148122403,545148285403,2755,"STEP_SEND_INPUT_EVENT_UI"
-2755,545148285403,34000,0,"STEP_SEND_INPUT_EVENT_UI",545148331403,545148361611,545148363611,2755,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2755,545148363611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545148372611,545156212611,545156217611,2755,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2755,545156217611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545156278611,545158108611,545158108611,2755,"STEP_SWAP_BUFFERS"
-2755,545158108611,8000,0,"STEP_SWAP_BUFFERS",545158116611,545158576829,545158576829,2755,"STEP_DRAW_AND_SWAP"
-2755,545158576829,7000,0,"STEP_DRAW_AND_SWAP",545158583829,545167947829,545167947829,2755,"End"
-2755,545167947829,2000,0,"End",545167949829,"[NULL]",545155000403,2757,"AsyncBegin"
-2757,545155000403,23321426,0,"AsyncBegin",545155000403,545156464403,545156600403,2757,"Begin"
-2757,545156600403,1000,0,"Begin",545156744403,545156464403,545156676403,2757,"STEP_SEND_INPUT_EVENT_UI"
-2757,545156676403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545156744403,545156762611,545156766611,2757,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2757,545156766611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545156774611,545167101611,545167104611,2757,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2757,545167104611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545167206611,545168969611,545168969611,2757,"STEP_SWAP_BUFFERS"
-2757,545168969611,7000,0,"STEP_SWAP_BUFFERS",545168976611,545169358829,545169358829,2757,"STEP_DRAW_AND_SWAP"
-2757,545169358829,6000,0,"STEP_DRAW_AND_SWAP",545169364829,545178356829,545178356829,2757,"End"
-2757,545178356829,8000,0,"End",545178364829,"[NULL]",545172000403,2761,"AsyncBegin"
-2761,545172000403,18585426,0,"AsyncBegin",545172000403,545173174403,545173356403,2761,"Begin"
-2761,545173356403,1000,0,"Begin",545173435403,545173174403,545173385403,2761,"STEP_SEND_INPUT_EVENT_UI"
-2761,545173385403,37000,0,"STEP_SEND_INPUT_EVENT_UI",545173435403,545173472611,545173475611,2761,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2761,545173475611,14000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545173490611,545178084611,545178088611,2761,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2761,545178088611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545178129611,545179809611,545179809611,2761,"STEP_SWAP_BUFFERS"
-2761,545179809611,7000,0,"STEP_SWAP_BUFFERS",545179816611,545180237829,545180237829,2761,"STEP_DRAW_AND_SWAP"
-2761,545180237829,6000,0,"STEP_DRAW_AND_SWAP",545180243829,545190593829,545190593829,2761,"End"
-2761,545190593829,2000,0,"End",545190595829,"[NULL]",545180000403,2763,"AsyncBegin"
-2763,545180000403,22430426,0,"AsyncBegin",545180000403,545181243403,545181398403,2763,"Begin"
-2763,545181398403,2000,0,"Begin",545181468403,545181243403,545181425403,2763,"STEP_SEND_INPUT_EVENT_UI"
-2763,545181425403,31000,0,"STEP_SEND_INPUT_EVENT_UI",545181468403,545181531611,545181536611,2763,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2763,545181536611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545181548611,545189118611,545189123611,2763,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2763,545189123611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545189173611,545191077611,545191077611,2763,"STEP_SWAP_BUFFERS"
-2763,545191077611,7000,0,"STEP_SWAP_BUFFERS",545191084611,545191465829,545191465829,2763,"STEP_DRAW_AND_SWAP"
-2763,545191465829,6000,0,"STEP_DRAW_AND_SWAP",545191471829,545202437829,545202437829,2763,"End"
-2763,545202437829,3000,0,"End",545202440829,"[NULL]",545188000403,2765,"AsyncBegin"
-2765,545188000403,23545426,0,"AsyncBegin",545188000403,545189976403,545190209403,2765,"Begin"
-2765,545190209403,1000,0,"Begin",545190322403,545189976403,545190240403,2765,"STEP_SEND_INPUT_EVENT_UI"
-2765,545190240403,67000,0,"STEP_SEND_INPUT_EVENT_UI",545190322403,545190513611,545190516611,2765,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2765,545190516611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545190526611,545200643611,545200646611,2765,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2765,545200646611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545200689611,545202604611,545202604611,2765,"STEP_SWAP_BUFFERS"
-2765,545202604611,8000,0,"STEP_SWAP_BUFFERS",545202612611,545202995829,545202995829,2765,"STEP_DRAW_AND_SWAP"
-2765,545202995829,5000,0,"STEP_DRAW_AND_SWAP",545203000829,545211553829,545211553829,2765,"End"
-2765,545211553829,2000,0,"End",545211555829,"[NULL]",545204000403,2769,"AsyncBegin"
-2769,545204000403,19115426,0,"AsyncBegin",545204000403,545206091403,545206301403,2769,"Begin"
-2769,545206301403,1000,0,"Begin",545206390403,545206091403,545206338403,2769,"STEP_SEND_INPUT_EVENT_UI"
-2769,545206338403,38000,0,"STEP_SEND_INPUT_EVENT_UI",545206390403,545206465611,545206467611,2769,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2769,545206467611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545206478611,545211411611,545211415611,2769,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2769,545211415611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545211456611,545213184611,545213184611,2769,"STEP_SWAP_BUFFERS"
-2769,545213184611,7000,0,"STEP_SWAP_BUFFERS",545213191611,545213608829,545213608829,2769,"STEP_DRAW_AND_SWAP"
-2769,545213608829,6000,0,"STEP_DRAW_AND_SWAP",545213614829,545223124829,545223124829,2769,"End"
-2769,545223124829,2000,0,"End",545223126829,"[NULL]",545213000403,2771,"AsyncBegin"
-2771,545213000403,21107426,0,"AsyncBegin",545213000403,545214147403,545214275403,2771,"Begin"
-2771,545214275403,1000,0,"Begin",545214340403,545214147403,545214299403,2771,"STEP_SEND_INPUT_EVENT_UI"
-2771,545214299403,31000,0,"STEP_SEND_INPUT_EVENT_UI",545214340403,545214374611,545214377611,2771,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2771,545214377611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545214385611,545222860611,545222864611,2771,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2771,545222864611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545222909611,545225019611,545225019611,2771,"STEP_SWAP_BUFFERS"
-2771,545225019611,9000,0,"STEP_SWAP_BUFFERS",545225028611,545225484829,545225484829,2771,"STEP_DRAW_AND_SWAP"
-2771,545225484829,9000,0,"STEP_DRAW_AND_SWAP",545225493829,545234115829,545234115829,2771,"End"
-2771,545234115829,2000,0,"End",545234117829,"[NULL]",545221000403,2773,"AsyncBegin"
-2773,545221000403,25065426,0,"AsyncBegin",545221000403,545226434403,545226563403,2773,"Begin"
-2773,545226563403,1000,0,"Begin",545226655403,545226434403,545226589403,2773,"STEP_SEND_INPUT_EVENT_UI"
-2773,545226589403,54000,0,"STEP_SEND_INPUT_EVENT_UI",545226655403,545226702611,545226704611,2773,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2773,545226704611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545226713611,545233818611,545233822611,2773,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2773,545233822611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545233859611,545237110611,545237110611,2773,"STEP_SWAP_BUFFERS"
-2773,545237110611,9000,0,"STEP_SWAP_BUFFERS",545237119611,545237603829,545237603829,2773,"STEP_DRAW_AND_SWAP"
-2773,545237603829,8000,0,"STEP_DRAW_AND_SWAP",545237611829,545246072829,545246072829,2773,"End"
-2773,545246072829,2000,0,"End",545246074829,"[NULL]",545237000403,2777,"AsyncBegin"
-2777,545237000403,20064426,0,"AsyncBegin",545237000403,545238907403,545239218403,2777,"Begin"
-2777,545239218403,1000,0,"Begin",545239371403,545238907403,545239246403,2777,"STEP_SEND_INPUT_EVENT_UI"
-2777,545239246403,112000,0,"STEP_SEND_INPUT_EVENT_UI",545239371403,545239325611,545239329611,2777,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2777,545239329611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545239339611,545244945611,545244948611,2777,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2777,545244948611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545244985611,545247198611,545247198611,2777,"STEP_SWAP_BUFFERS"
-2777,545247198611,6000,0,"STEP_SWAP_BUFFERS",545247204611,545247607829,545247607829,2777,"STEP_DRAW_AND_SWAP"
-2777,545247607829,7000,0,"STEP_DRAW_AND_SWAP",545247614829,545257072829,545257072829,2777,"End"
-2777,545257072829,2000,0,"End",545257074829,"[NULL]",545246000403,2779,"AsyncBegin"
-2779,545246000403,22190426,0,"AsyncBegin",545246000403,545247150403,545247287403,2779,"Begin"
-2779,545247287403,1000,0,"Begin",545247359403,545247150403,545247310403,2779,"STEP_SEND_INPUT_EVENT_UI"
-2779,545247310403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545247359403,545247400611,545247403611,2779,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2779,545247403611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545247411611,545256043611,545256046611,2779,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2779,545256046611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545256079611,545258338611,545258338611,2779,"STEP_SWAP_BUFFERS"
-2779,545258338611,7000,0,"STEP_SWAP_BUFFERS",545258345611,545258748829,545258748829,2779,"STEP_DRAW_AND_SWAP"
-2779,545258748829,6000,0,"STEP_DRAW_AND_SWAP",545258754829,545268197829,545268197829,2779,"End"
-2779,545268197829,2000,0,"End",545268199829,"[NULL]",545262000403,2783,"AsyncBegin"
-2783,545262000403,16635426,0,"AsyncBegin",545262000403,545263402403,545263579403,2783,"Begin"
-2783,545263579403,1000,0,"Begin",545263654403,545263402403,545263606403,2783,"STEP_SEND_INPUT_EVENT_UI"
-2783,545263606403,35000,0,"STEP_SEND_INPUT_EVENT_UI",545263654403,545263695611,545263698611,2783,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2783,545263698611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545263707611,545267807611,545267811611,2783,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2783,545267811611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545267849611,545269500611,545269500611,2783,"STEP_SWAP_BUFFERS"
-2783,545269500611,7000,0,"STEP_SWAP_BUFFERS",545269507611,545269887829,545269887829,2783,"STEP_DRAW_AND_SWAP"
-2783,545269887829,6000,0,"STEP_DRAW_AND_SWAP",545269893829,545278645829,545278645829,2783,"End"
-2783,545278645829,1000,0,"End",545278646829,"[NULL]",545270000403,2785,"AsyncBegin"
-2785,545270000403,19926426,0,"AsyncBegin",545270000403,545271631403,545271774403,2785,"Begin"
-2785,545271774403,1000,0,"Begin",545271847403,545271631403,545271799403,2785,"STEP_SEND_INPUT_EVENT_UI"
-2785,545271799403,35000,0,"STEP_SEND_INPUT_EVENT_UI",545271847403,545271884611,545271887611,2785,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2785,545271887611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545271897611,545278776611,545278780611,2785,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2785,545278780611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545278814611,545282047611,545282047611,2785,"STEP_SWAP_BUFFERS"
-2785,545282047611,7000,0,"STEP_SWAP_BUFFERS",545282054611,545282493829,545282493829,2785,"STEP_DRAW_AND_SWAP"
-2785,545282493829,7000,0,"STEP_DRAW_AND_SWAP",545282500829,545289934829,545289934829,2785,"End"
-2785,545289934829,3000,0,"End",545289937829,"[NULL]",545278000403,2787,"AsyncBegin"
-2787,545278000403,23003426,0,"AsyncBegin",545278000403,545279835403,545280350403,2787,"Begin"
-2787,545280350403,1000,0,"Begin",545280508403,545279835403,545280379403,2787,"STEP_SEND_INPUT_EVENT_UI"
-2787,545280379403,114000,0,"STEP_SEND_INPUT_EVENT_UI",545280508403,545280459611,545280463611,2787,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2787,545280463611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545280474611,545289598611,545289602611,2787,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2787,545289602611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545289638611,545291851611,545291851611,2787,"STEP_SWAP_BUFFERS"
-2787,545291851611,7000,0,"STEP_SWAP_BUFFERS",545291858611,545292308829,545292308829,2787,"STEP_DRAW_AND_SWAP"
-2787,545292308829,6000,0,"STEP_DRAW_AND_SWAP",545292314829,545301010829,545301010829,2787,"End"
-2787,545301010829,3000,0,"End",545301013829,"[NULL]",545295000403,2791,"AsyncBegin"
-2791,545295000403,17169426,0,"AsyncBegin",545295000403,545296719403,545296876403,2791,"Begin"
-2791,545296876403,2000,0,"Begin",545296947403,545296719403,545296903403,2791,"STEP_SEND_INPUT_EVENT_UI"
-2791,545296903403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545296947403,545296994611,545296996611,2791,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2791,545296996611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545297005611,545300799611,545300803611,2791,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2791,545300803611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545300842611,545303115611,545303115611,2791,"STEP_SWAP_BUFFERS"
-2791,545303115611,8000,0,"STEP_SWAP_BUFFERS",545303123611,545303582829,545303582829,2791,"STEP_DRAW_AND_SWAP"
-2791,545303582829,6000,0,"STEP_DRAW_AND_SWAP",545303588829,545312177829,545312177829,2791,"End"
-2791,545312177829,3000,0,"End",545312180829,"[NULL]",545303000403,2793,"AsyncBegin"
-2793,545303000403,20626426,0,"AsyncBegin",545303000403,545304395403,545304562403,2793,"Begin"
-2793,545304562403,2000,0,"Begin",545304626403,545304395403,545304589403,2793,"STEP_SEND_INPUT_EVENT_UI"
-2793,545304589403,26000,0,"STEP_SEND_INPUT_EVENT_UI",545304626403,545304897611,545304899611,2793,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2793,545304899611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545304909611,545311974611,545311978611,2793,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2793,545311978611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545312021611,545314631611,545314631611,2793,"STEP_SWAP_BUFFERS"
-2793,545314631611,7000,0,"STEP_SWAP_BUFFERS",545314638611,545315150829,545315150829,2793,"STEP_DRAW_AND_SWAP"
-2793,545315150829,9000,0,"STEP_DRAW_AND_SWAP",545315159829,545323633829,545323633829,2793,"End"
-2793,545323633829,2000,0,"End",545323635829,"[NULL]",545311000403,2795,"AsyncBegin"
-2795,545311000403,23560426,0,"AsyncBegin",545311000403,545312582403,545312703403,2795,"Begin"
-2795,545312703403,1000,0,"Begin",545312768403,545312582403,545312729403,2795,"STEP_SEND_INPUT_EVENT_UI"
-2795,545312729403,28000,0,"STEP_SEND_INPUT_EVENT_UI",545312768403,545312811611,545312813611,2795,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2795,545312813611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545312823611,545323089611,545323093611,2795,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2795,545323093611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545323131611,545325014611,545325014611,2795,"STEP_SWAP_BUFFERS"
-2795,545325014611,6000,0,"STEP_SWAP_BUFFERS",545325020611,545325412829,545325412829,2795,"STEP_DRAW_AND_SWAP"
-2795,545325412829,6000,0,"STEP_DRAW_AND_SWAP",545325418829,545334569829,545334569829,2795,"End"
-2795,545334569829,2000,0,"End",545334571829,"[NULL]",545328000403,2799,"AsyncBegin"
-2799,545328000403,18191426,0,"AsyncBegin",545328000403,545329466403,545329632403,2799,"Begin"
-2799,545329632403,1000,0,"Begin",545329713403,545329466403,545329664403,2799,"STEP_SEND_INPUT_EVENT_UI"
-2799,545329664403,37000,0,"STEP_SEND_INPUT_EVENT_UI",545329713403,545329815611,545329818611,2799,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2799,545329818611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545329830611,545334454611,545334458611,2799,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2799,545334458611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545334499611,545336543611,545336543611,2799,"STEP_SWAP_BUFFERS"
-2799,545336543611,7000,0,"STEP_SWAP_BUFFERS",545336550611,545336987829,545336987829,2799,"STEP_DRAW_AND_SWAP"
-2799,545336987829,8000,0,"STEP_DRAW_AND_SWAP",545336995829,545346227829,545346227829,2799,"End"
-2799,545346227829,8000,0,"End",545346235829,"[NULL]",545336000403,2801,"AsyncBegin"
-2801,545336000403,20911426,0,"AsyncBegin",545336000403,545337538403,545337677403,2801,"Begin"
-2801,545337677403,1000,0,"Begin",545337747403,545337538403,545337702403,2801,"STEP_SEND_INPUT_EVENT_UI"
-2801,545337702403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545337747403,545337769611,545337771611,2801,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2801,545337771611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545337780611,545345503611,545345508611,2801,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2801,545345508611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545345552611,545347962611,545347962611,2801,"STEP_SWAP_BUFFERS"
-2801,545347962611,7000,0,"STEP_SWAP_BUFFERS",545347969611,545348403829,545348403829,2801,"STEP_DRAW_AND_SWAP"
-2801,545348403829,6000,0,"STEP_DRAW_AND_SWAP",545348409829,545356918829,545356918829,2801,"End"
-2801,545356918829,2000,0,"End",545356920829,"[NULL]",545344000403,2803,"AsyncBegin"
-2803,545344000403,24228426,0,"AsyncBegin",545344000403,545345599403,545345731403,2803,"Begin"
-2803,545345731403,1000,0,"Begin",545345793403,545345599403,545345757403,2803,"STEP_SEND_INPUT_EVENT_UI"
-2803,545345757403,26000,0,"STEP_SEND_INPUT_EVENT_UI",545345793403,545345808611,545345810611,2803,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2803,545345810611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545345818611,545356727611,545356732611,2803,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2803,545356732611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545356870611,545359100611,545359100611,2803,"STEP_SWAP_BUFFERS"
-2803,545359100611,8000,0,"STEP_SWAP_BUFFERS",545359108611,545359582829,545359582829,2803,"STEP_DRAW_AND_SWAP"
-2803,545359582829,8000,0,"STEP_DRAW_AND_SWAP",545359590829,545368235829,545368235829,2803,"End"
-2803,545368235829,2000,0,"End",545368237829,"[NULL]",545361000403,2807,"AsyncBegin"
-2807,545361000403,18189426,0,"AsyncBegin",545361000403,545362126403,545362271403,2807,"Begin"
-2807,545362271403,2000,0,"Begin",545362343403,545362126403,545362297403,2807,"STEP_SEND_INPUT_EVENT_UI"
-2807,545362297403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545362343403,545362382611,545362384611,2807,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2807,545362384611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545362394611,545367793611,545367796611,2807,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2807,545367796611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545367837611,545370187611,545370187611,2807,"STEP_SWAP_BUFFERS"
-2807,545370187611,7000,0,"STEP_SWAP_BUFFERS",545370194611,545370654829,545370654829,2807,"STEP_DRAW_AND_SWAP"
-2807,545370654829,7000,0,"STEP_DRAW_AND_SWAP",545370661829,545379195829,545379195829,2807,"End"
-2807,545379195829,2000,0,"End",545379197829,"[NULL]",545369000403,2809,"AsyncBegin"
-2809,545369000403,21379426,0,"AsyncBegin",545369000403,545370539403,545370671403,2809,"Begin"
-2809,545370671403,1000,0,"Begin",545370733403,545370539403,545370696403,2809,"STEP_SEND_INPUT_EVENT_UI"
-2809,545370696403,26000,0,"STEP_SEND_INPUT_EVENT_UI",545370733403,545370891611,545370894611,2809,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2809,545370894611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545370901611,545379191611,545379195611,2809,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2809,545379195611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545379232611,545381354611,545381354611,2809,"STEP_SWAP_BUFFERS"
-2809,545381354611,7000,0,"STEP_SWAP_BUFFERS",545381361611,545381908829,545381908829,2809,"STEP_DRAW_AND_SWAP"
-2809,545381908829,8000,0,"STEP_DRAW_AND_SWAP",545381916829,545390387829,545390387829,2809,"End"
-2809,545390387829,2000,0,"End",545390389829,"[NULL]",545377000403,2811,"AsyncBegin"
-2811,545377000403,24913426,0,"AsyncBegin",545377000403,545378570403,545378746403,2811,"Begin"
-2811,545378746403,2000,0,"Begin",545378810403,545378570403,545378773403,2811,"STEP_SEND_INPUT_EVENT_UI"
-2811,545378773403,25000,0,"STEP_SEND_INPUT_EVENT_UI",545378810403,545379369611,545379371611,2811,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2811,545379371611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545379379611,545390128611,545390130611,2811,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2811,545390130611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545390169611,545391924611,545391924611,2811,"STEP_SWAP_BUFFERS"
-2811,545391924611,8000,0,"STEP_SWAP_BUFFERS",545391932611,545392344829,545392344829,2811,"STEP_DRAW_AND_SWAP"
-2811,545392344829,6000,0,"STEP_DRAW_AND_SWAP",545392350829,545401921829,545401921829,2811,"End"
-2811,545401921829,3000,0,"End",545401924829,"[NULL]",545394000403,2815,"AsyncBegin"
-2815,545394000403,18671426,0,"AsyncBegin",545394000403,545395127403,545395267403,2815,"Begin"
-2815,545395267403,1000,0,"Begin",545395366403,545395127403,545395293403,2815,"STEP_SEND_INPUT_EVENT_UI"
-2815,545395293403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545395366403,545395369611,545395371611,2815,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2815,545395371611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545395381611,545401928611,545401932611,2815,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2815,545401932611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545401973611,545403806611,545403806611,2815,"STEP_SWAP_BUFFERS"
-2815,545403806611,5000,0,"STEP_SWAP_BUFFERS",545403811611,545404248829,545404248829,2815,"STEP_DRAW_AND_SWAP"
-2815,545404248829,7000,0,"STEP_DRAW_AND_SWAP",545404255829,545412677829,545412677829,2815,"End"
-2815,545412677829,2000,0,"End",545412679829,"[NULL]",545402000403,2817,"AsyncBegin"
-2817,545402000403,21928426,0,"AsyncBegin",545402000403,545403261403,545403464403,2817,"Begin"
-2817,545403464403,2000,0,"Begin",545403612403,545403261403,545403500403,2817,"STEP_SEND_INPUT_EVENT_UI"
-2817,545403500403,94000,0,"STEP_SEND_INPUT_EVENT_UI",545403612403,545403638611,545403640611,2817,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2817,545403640611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545403649611,545412460611,545412464611,2817,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2817,545412464611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545412499611,545414635611,545414635611,2817,"STEP_SWAP_BUFFERS"
-2817,545414635611,7000,0,"STEP_SWAP_BUFFERS",545414642611,545415059829,545415059829,2817,"STEP_DRAW_AND_SWAP"
-2817,545415059829,8000,0,"STEP_DRAW_AND_SWAP",545415067829,545423937829,545423937829,2817,"End"
-2817,545423937829,2000,0,"End",545423939829,"[NULL]",545418000403,2821,"AsyncBegin"
-2821,545418000403,17254426,0,"AsyncBegin",545418000403,545419737403,545419886403,2821,"Begin"
-2821,545419886403,1000,0,"Begin",545420035403,545419737403,545419912403,2821,"STEP_SEND_INPUT_EVENT_UI"
-2821,545419912403,82000,0,"STEP_SEND_INPUT_EVENT_UI",545420035403,545420065611,545420068611,2821,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2821,545420068611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545420077611,545424059611,545424063611,2821,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2821,545424063611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545424099611,545425917611,545425917611,2821,"STEP_SWAP_BUFFERS"
-2821,545425917611,8000,0,"STEP_SWAP_BUFFERS",545425925611,545426405829,545426405829,2821,"STEP_DRAW_AND_SWAP"
-2821,545426405829,8000,0,"STEP_DRAW_AND_SWAP",545426413829,545435262829,545435262829,2821,"End"
-2821,545435262829,2000,0,"End",545435264829,"[NULL]",545426000403,2823,"AsyncBegin"
-2823,545426000403,20407426,0,"AsyncBegin",545426000403,545427922403,545428064403,2823,"Begin"
-2823,545428064403,1000,0,"Begin",545428132403,545427922403,545428090403,2823,"STEP_SEND_INPUT_EVENT_UI"
-2823,545428090403,31000,0,"STEP_SEND_INPUT_EVENT_UI",545428132403,545428176611,545428179611,2823,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2823,545428179611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545428188611,545435214611,545435218611,2823,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2823,545435218611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545435259611,545437410611,545437410611,2823,"STEP_SWAP_BUFFERS"
-2823,545437410611,6000,0,"STEP_SWAP_BUFFERS",545437416611,545437842829,545437842829,2823,"STEP_DRAW_AND_SWAP"
-2823,545437842829,8000,0,"STEP_DRAW_AND_SWAP",545437850829,545446415829,545446415829,2823,"End"
-2823,545446415829,2000,0,"End",545446417829,"[NULL]",545435000403,2825,"AsyncBegin"
-2825,545435000403,22633426,0,"AsyncBegin",545435000403,545435980403,545436098403,2825,"Begin"
-2825,545436098403,2000,0,"Begin",545436165403,545435980403,545436123403,2825,"STEP_SEND_INPUT_EVENT_UI"
-2825,545436123403,31000,0,"STEP_SEND_INPUT_EVENT_UI",545436165403,545436192611,545436194611,2825,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2825,545436194611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545436203611,545446061611,545446064611,2825,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2825,545446064611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545446102611,545447864611,545447864611,2825,"STEP_SWAP_BUFFERS"
-2825,545447864611,9000,0,"STEP_SWAP_BUFFERS",545447873611,545448362829,545448362829,2825,"STEP_DRAW_AND_SWAP"
-2825,545448362829,6000,0,"STEP_DRAW_AND_SWAP",545448368829,545457639829,545457639829,2825,"End"
-2825,545457639829,2000,0,"End",545457641829,"[NULL]",545443000403,2827,"AsyncBegin"
-2827,545443000403,27179426,0,"AsyncBegin",545443000403,545445387403,545445525403,2827,"Begin"
-2827,545445525403,1000,0,"Begin",545445588403,545445387403,545445550403,2827,"STEP_SEND_INPUT_EVENT_UI"
-2827,545445550403,27000,0,"STEP_SEND_INPUT_EVENT_UI",545445588403,545446153611,545446157611,2827,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2827,545446157611,12000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545446171611,545457190611,545457194611,2827,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2827,545457194611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545457236611,545458991611,545458991611,2827,"STEP_SWAP_BUFFERS"
-2827,545458991611,7000,0,"STEP_SWAP_BUFFERS",545458998611,545459400829,545459400829,2827,"STEP_DRAW_AND_SWAP"
-2827,545459400829,6000,0,"STEP_DRAW_AND_SWAP",545459406829,545470185829,545470185829,2827,"End"
-2827,545470185829,3000,0,"End",545470188829,"[NULL]",545459000403,2831,"AsyncBegin"
-2831,545459000403,20575426,0,"AsyncBegin",545459000403,545460996403,545461134403,2831,"Begin"
-2831,545461134403,1000,0,"Begin",545461206403,545460996403,545461161403,2831,"STEP_SEND_INPUT_EVENT_UI"
-2831,545461161403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545461206403,545461254611,545461257611,2831,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2831,545461257611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545461266611,545468705611,545468709611,2831,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2831,545468709611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545468753611,545470512611,545470512611,2831,"STEP_SWAP_BUFFERS"
-2831,545470512611,7000,0,"STEP_SWAP_BUFFERS",545470519611,545470980829,545470980829,2831,"STEP_DRAW_AND_SWAP"
-2831,545470980829,6000,0,"STEP_DRAW_AND_SWAP",545470986829,545479583829,545479583829,2831,"End"
-2831,545479583829,2000,0,"End",545479585829,"[NULL]",545468000403,2833,"AsyncBegin"
-2833,545468000403,23489426,0,"AsyncBegin",545468000403,545469430403,545469546403,2833,"Begin"
-2833,545469546403,2000,0,"Begin",545469638403,545469430403,545469572403,2833,"STEP_SEND_INPUT_EVENT_UI"
-2833,545469572403,55000,0,"STEP_SEND_INPUT_EVENT_UI",545469638403,545469916611,545469918611,2833,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2833,545469918611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545469927611,545479511611,545479515611,2833,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2833,545479515611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545479552611,545481211611,545481211611,2833,"STEP_SWAP_BUFFERS"
-2833,545481211611,6000,0,"STEP_SWAP_BUFFERS",545481217611,545481612829,545481612829,2833,"STEP_DRAW_AND_SWAP"
-2833,545481612829,7000,0,"STEP_DRAW_AND_SWAP",545481619829,545491497829,545491497829,2833,"End"
-2833,545491497829,2000,0,"End",545491499829,"[NULL]",545484000403,2837,"AsyncBegin"
-2837,545484000403,18277426,0,"AsyncBegin",545484000403,545485501403,545485672403,2837,"Begin"
-2837,545485672403,2000,0,"Begin",545485752403,545485501403,545485703403,2837,"STEP_SEND_INPUT_EVENT_UI"
-2837,545485703403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545485752403,545485821611,545485824611,2837,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2837,545485824611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545485835611,545491127611,545491131611,2837,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2837,545491131611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545491175611,545493207611,545493207611,2837,"STEP_SWAP_BUFFERS"
-2837,545493207611,7000,0,"STEP_SWAP_BUFFERS",545493214611,545493655829,545493655829,2837,"STEP_DRAW_AND_SWAP"
-2837,545493655829,8000,0,"STEP_DRAW_AND_SWAP",545493663829,545502285829,545502285829,2837,"End"
-2837,545502285829,2000,0,"End",545502287829,"[NULL]",545492000403,2839,"AsyncBegin"
-2839,545492000403,21649426,0,"AsyncBegin",545492000403,545493813403,545494062403,2839,"Begin"
-2839,545494062403,1000,0,"Begin",545494175403,545493813403,545494122403,2839,"STEP_SEND_INPUT_EVENT_UI"
-2839,545494122403,38000,0,"STEP_SEND_INPUT_EVENT_UI",545494175403,545494238611,545494243611,2839,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2839,545494243611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545494254611,545502007611,545502011611,2839,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2839,545502011611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545502056611,545504796611,545504796611,2839,"STEP_SWAP_BUFFERS"
-2839,545504796611,6000,0,"STEP_SWAP_BUFFERS",545504802611,545505248829,545505248829,2839,"STEP_DRAW_AND_SWAP"
-2839,545505248829,8000,0,"STEP_DRAW_AND_SWAP",545505256829,545513681829,545513681829,2839,"End"
-2839,545513681829,7000,0,"End",545513688829,"[NULL]",545500000403,2841,"AsyncBegin"
-2841,545500000403,24734426,0,"AsyncBegin",545500000403,545502616403,545502751403,2841,"Begin"
-2841,545502751403,2000,0,"Begin",545502821403,545502616403,545502779403,2841,"STEP_SEND_INPUT_EVENT_UI"
-2841,545502779403,30000,0,"STEP_SEND_INPUT_EVENT_UI",545502821403,545502846611,545502849611,2841,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2841,545502849611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545502858611,545513030611,545513059611,2841,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2841,545513059611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545513101611,545515481611,545515481611,2841,"STEP_SWAP_BUFFERS"
-2841,545515481611,8000,0,"STEP_SWAP_BUFFERS",545515489611,545515917829,545515917829,2841,"STEP_DRAW_AND_SWAP"
-2841,545515917829,6000,0,"STEP_DRAW_AND_SWAP",545515923829,545524742829,545524742829,2841,"End"
-2841,545524742829,2000,0,"End",545524744829,"[NULL]",545517000403,2845,"AsyncBegin"
-2845,545517000403,18824426,0,"AsyncBegin",545517000403,545518318403,545518468403,2845,"Begin"
-2845,545518468403,1000,0,"Begin",545518586403,545518318403,545518528403,2845,"STEP_SEND_INPUT_EVENT_UI"
-2845,545518528403,44000,0,"STEP_SEND_INPUT_EVENT_UI",545518586403,545518636611,545518639611,2845,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2845,545518639611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545518649611,545524570611,545524575611,2845,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2845,545524575611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545524628611,545526711611,545526711611,2845,"STEP_SWAP_BUFFERS"
-2845,545526711611,7000,0,"STEP_SWAP_BUFFERS",545526718611,545527190829,545527190829,2845,"STEP_DRAW_AND_SWAP"
-2845,545527190829,7000,0,"STEP_DRAW_AND_SWAP",545527197829,545535831829,545535831829,2845,"End"
-2845,545535831829,2000,0,"End",545535833829,"[NULL]",545525000403,2847,"AsyncBegin"
-2847,545525000403,22343426,0,"AsyncBegin",545525000403,545526525403,545526694403,2847,"Begin"
-2847,545526694403,1000,0,"Begin",545526776403,545526525403,545526724403,2847,"STEP_SEND_INPUT_EVENT_UI"
-2847,545526724403,40000,0,"STEP_SEND_INPUT_EVENT_UI",545526776403,545526918611,545526920611,2847,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2847,545526920611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545526928611,545535499611,545535502611,2847,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2847,545535502611,1000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545535536611,545537200611,545537200611,2847,"STEP_SWAP_BUFFERS"
-2847,545537200611,7000,0,"STEP_SWAP_BUFFERS",545537207611,545537622829,545537622829,2847,"STEP_DRAW_AND_SWAP"
-2847,545537622829,7000,0,"STEP_DRAW_AND_SWAP",545537629829,545547352829,545547352829,2847,"End"
-2847,545547352829,6000,0,"End",545547358829,"[NULL]",545533000403,2849,"AsyncBegin"
-2849,545533000403,25222426,0,"AsyncBegin",545533000403,545534953403,545535099403,2849,"Begin"
-2849,545535099403,1000,0,"Begin",545535160403,545534953403,545535125403,2849,"STEP_SEND_INPUT_EVENT_UI"
-2849,545535125403,24000,0,"STEP_SEND_INPUT_EVENT_UI",545535160403,545535588611,545535592611,2849,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2849,545535592611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545535601611,545546698611,545546704611,2849,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2849,545546704611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545546740611,545548503611,545548503611,2849,"STEP_SWAP_BUFFERS"
-2849,545548503611,9000,0,"STEP_SWAP_BUFFERS",545548512611,545548920829,545548920829,2849,"STEP_DRAW_AND_SWAP"
-2849,545548920829,5000,0,"STEP_DRAW_AND_SWAP",545548925829,545558230829,545558230829,2849,"End"
-2849,545558230829,3000,0,"End",545558233829,"[NULL]",545550000403,2853,"AsyncBegin"
-2853,545550000403,19151426,0,"AsyncBegin",545550000403,545551042403,545551389403,2853,"Begin"
-2853,545551389403,2000,0,"Begin",545551573403,545551042403,545551421403,2853,"STEP_SEND_INPUT_EVENT_UI"
-2853,545551421403,136000,0,"STEP_SEND_INPUT_EVENT_UI",545551573403,545551517611,545551522611,2853,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2853,545551522611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545551534611,545558062611,545558067611,2853,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2853,545558067611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545558111611,545560260611,545560260611,2853,"STEP_SWAP_BUFFERS"
-2853,545560260611,6000,0,"STEP_SWAP_BUFFERS",545560266611,545560689829,545560689829,2853,"STEP_DRAW_AND_SWAP"
-2853,545560689829,8000,0,"STEP_DRAW_AND_SWAP",545560697829,545569158829,545569158829,2853,"End"
-2853,545569158829,1000,0,"End",545569159829,"[NULL]",545558000403,2855,"AsyncBegin"
-2855,545558000403,22660426,0,"AsyncBegin",545558000403,545559432403,545559561403,2855,"Begin"
-2855,545559561403,1000,0,"Begin",545559633403,545559432403,545559587403,2855,"STEP_SEND_INPUT_EVENT_UI"
-2855,545559587403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545559633403,545559679611,545559682611,2855,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2855,545559682611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545559692611,545568903611,545568906611,2855,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2855,545568906611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545569011611,545571019611,545571019611,2855,"STEP_SWAP_BUFFERS"
-2855,545571019611,7000,0,"STEP_SWAP_BUFFERS",545571026611,545571437829,545571437829,2855,"STEP_DRAW_AND_SWAP"
-2855,545571437829,7000,0,"STEP_DRAW_AND_SWAP",545571444829,545580670829,545580670829,2855,"End"
-2855,545580670829,2000,0,"End",545580672829,"[NULL]",545574000403,2859,"AsyncBegin"
-2859,545574000403,17603426,0,"AsyncBegin",545574000403,545575964403,545576109403,2859,"Begin"
-2859,545576109403,1000,0,"Begin",545576180403,545575964403,545576135403,2859,"STEP_SEND_INPUT_EVENT_UI"
-2859,545576135403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545576180403,545576217611,545576219611,2859,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2859,545576219611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545576228611,545581056611,545581062611,2859,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2859,545581062611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545581108611,545582986611,545582986611,2859,"STEP_SWAP_BUFFERS"
-2859,545582986611,7000,0,"STEP_SWAP_BUFFERS",545582993611,545583484829,545583484829,2859,"STEP_DRAW_AND_SWAP"
-2859,545583484829,7000,0,"STEP_DRAW_AND_SWAP",545583491829,545591611829,545591611829,2859,"End"
-2859,545591611829,2000,0,"End",545591613829,"[NULL]",545583000403,2861,"AsyncBegin"
-2861,545583000403,19608426,0,"AsyncBegin",545583000403,545584292403,545584432403,2861,"Begin"
-2861,545584432403,1000,0,"Begin",545584503403,545584292403,545584458403,2861,"STEP_SEND_INPUT_EVENT_UI"
-2861,545584458403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545584503403,545584525611,545584527611,2861,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2861,545584527611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545584537611,545591605611,545591609611,2861,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2861,545591609611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545591652611,545594008611,545594008611,2861,"STEP_SWAP_BUFFERS"
-2861,545594008611,6000,0,"STEP_SWAP_BUFFERS",545594014611,545594448829,545594448829,2861,"STEP_DRAW_AND_SWAP"
-2861,545594448829,8000,0,"STEP_DRAW_AND_SWAP",545594456829,545602616829,545602616829,2861,"End"
-2861,545602616829,2000,0,"End",545602618829,"[NULL]",545591000403,2863,"AsyncBegin"
-2863,545591000403,22822426,0,"AsyncBegin",545591000403,545592149403,545592267403,2863,"Begin"
-2863,545592267403,28000,0,"Begin",545592370403,545592149403,545592323403,2863,"STEP_SEND_INPUT_EVENT_UI"
-2863,545592323403,34000,0,"STEP_SEND_INPUT_EVENT_UI",545592370403,545592608611,545592613611,2863,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2863,545592613611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545592645611,545603135611,545603139611,2863,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2863,545603139611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545603221611,545605222611,545605222611,2863,"STEP_SWAP_BUFFERS"
-2863,545605222611,7000,0,"STEP_SWAP_BUFFERS",545605229611,545605636829,545605636829,2863,"STEP_DRAW_AND_SWAP"
-2863,545605636829,6000,0,"STEP_DRAW_AND_SWAP",545605642829,545613831829,545613831829,2863,"End"
-2863,545613831829,2000,0,"End",545613833829,"[NULL]",545607000403,2867,"AsyncBegin"
-2867,545607000403,18005426,0,"AsyncBegin",545607000403,545608899403,545609050403,2867,"Begin"
-2867,545609050403,2000,0,"Begin",545609125403,545608899403,545609081403,2867,"STEP_SEND_INPUT_EVENT_UI"
-2867,545609081403,32000,0,"STEP_SEND_INPUT_EVENT_UI",545609125403,545609151611,545609153611,2867,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2867,545609153611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545609162611,545614173611,545614177611,2867,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2867,545614177611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545614211611,545615903611,545615903611,2867,"STEP_SWAP_BUFFERS"
-2867,545615903611,7000,0,"STEP_SWAP_BUFFERS",545615910611,545616332829,545616332829,2867,"STEP_DRAW_AND_SWAP"
-2867,545616332829,7000,0,"STEP_DRAW_AND_SWAP",545616339829,545625013829,545625013829,2867,"End"
-2867,545625013829,2000,0,"End",545625015829,"[NULL]",545615000403,2869,"AsyncBegin"
-2869,545615000403,21063426,0,"AsyncBegin",545615000403,545617943403,545618417403,2869,"Begin"
-2869,545618417403,2000,0,"Begin",545618492403,545617943403,545618446403,2869,"STEP_SEND_INPUT_EVENT_UI"
-2869,545618446403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545618492403,545618582611,545618589611,2869,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2869,545618589611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545618600611,545624819611,545624822611,2869,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2869,545624822611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545624863611,545626738611,545626738611,2869,"STEP_SWAP_BUFFERS"
-2869,545626738611,6000,0,"STEP_SWAP_BUFFERS",545626744611,545627143829,545627143829,2869,"STEP_DRAW_AND_SWAP"
-2869,545627143829,7000,0,"STEP_DRAW_AND_SWAP",545627150829,545636070829,545636070829,2869,"End"
-2869,545636070829,1000,0,"End",545636071829,"[NULL]",545624000403,2871,"AsyncBegin"
-2871,545624000403,23894426,0,"AsyncBegin",545624000403,545625078403,545625201403,2871,"Begin"
-2871,545625201403,2000,0,"Begin",545625268403,545625078403,545625227403,2871,"STEP_SEND_INPUT_EVENT_UI"
-2871,545625227403,29000,0,"STEP_SEND_INPUT_EVENT_UI",545625268403,545625287611,545625289611,2871,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2871,545625289611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545625297611,545635894611,545635898611,2871,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2871,545635898611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545635933611,545637871611,545637871611,2871,"STEP_SWAP_BUFFERS"
-2871,545637871611,7000,0,"STEP_SWAP_BUFFERS",545637878611,545638300829,545638300829,2871,"STEP_DRAW_AND_SWAP"
-2871,545638300829,7000,0,"STEP_DRAW_AND_SWAP",545638307829,545647901829,545647901829,2871,"End"
-2871,545647901829,2000,0,"End",545647903829,"[NULL]",545640000403,2875,"AsyncBegin"
-2875,545640000403,18611426,0,"AsyncBegin",545640000403,545641559403,545641729403,2875,"Begin"
-2875,545641729403,1000,0,"Begin",545641805403,545641559403,545641755403,2875,"STEP_SEND_INPUT_EVENT_UI"
-2875,545641755403,37000,0,"STEP_SEND_INPUT_EVENT_UI",545641805403,545641850611,545641854611,2875,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2875,545641854611,13000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545641869611,545647619611,545647653611,2875,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2875,545647653611,7000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545647700611,545649619611,545649619611,2875,"STEP_SWAP_BUFFERS"
-2875,545649619611,9000,0,"STEP_SWAP_BUFFERS",545649628611,545650133829,545650133829,2875,"STEP_DRAW_AND_SWAP"
-2875,545650133829,7000,0,"STEP_DRAW_AND_SWAP",545650140829,545658618829,545658618829,2875,"End"
-2875,545658618829,2000,0,"End",545658620829,"[NULL]",545648000403,2877,"AsyncBegin"
-2877,545648000403,21759426,0,"AsyncBegin",545648000403,545649858403,545650030403,2877,"Begin"
-2877,545650030403,2000,0,"Begin",545650114403,545649858403,545650064403,2877,"STEP_SEND_INPUT_EVENT_UI"
-2877,545650064403,37000,0,"STEP_SEND_INPUT_EVENT_UI",545650114403,545650134611,545650137611,2877,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2877,545650137611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545650146611,545658312611,545658316611,2877,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2877,545658316611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545658354611,545660121611,545660121611,2877,"STEP_SWAP_BUFFERS"
-2877,545660121611,7000,0,"STEP_SWAP_BUFFERS",545660128611,545660549829,545660549829,2877,"STEP_DRAW_AND_SWAP"
-2877,545660549829,7000,0,"STEP_DRAW_AND_SWAP",545660556829,545669767829,545669767829,2877,"End"
-2877,545669767829,2000,0,"End",545669769829,"[NULL]",545656000403,2879,"AsyncBegin"
-2879,545656000403,25004426,0,"AsyncBegin",545656000403,545657848403,545657990403,2879,"Begin"
-2879,545657990403,1000,0,"Begin",545658050403,545657848403,545658015403,2879,"STEP_SEND_INPUT_EVENT_UI"
-2879,545658015403,24000,0,"STEP_SEND_INPUT_EVENT_UI",545658050403,545658466611,545658469611,2879,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2879,545658469611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545658477611,545669774611,545669778611,2879,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2879,545669778611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545669828611,545672231611,545672231611,2879,"STEP_SWAP_BUFFERS"
-2879,545672231611,7000,0,"STEP_SWAP_BUFFERS",545672238611,545672662829,545672662829,2879,"STEP_DRAW_AND_SWAP"
-2879,545672662829,7000,0,"STEP_DRAW_AND_SWAP",545672669829,545681056829,545681056829,2879,"End"
-2879,545681056829,8000,0,"End",545681064829,"[NULL]",545671000403,2881,"AsyncBegin"
-2881,545671000403,32742426,0,"AsyncBegin",545671000403,545673069403,545673257403,2881,"Begin"
-2881,545673257403,1000,0,"Begin",545673352403,545673069403,545673304403,2881,"STEP_SEND_INPUT_EVENT_UI"
-2881,545673304403,36000,0,"STEP_SEND_INPUT_EVENT_UI",545673352403,545673613611,545673616611,2881,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2881,545673616611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545673626611,545681144611,545681149611,2881,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2881,545681149611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545681185611,545687519611,545687519611,2881,"STEP_SWAP_BUFFERS"
-2881,545687519611,6000,0,"STEP_SWAP_BUFFERS",545687525611,545688029829,545688029829,2881,"STEP_DRAW_AND_SWAP"
-2881,545688029829,7000,0,"STEP_DRAW_AND_SWAP",545688036829,545703750829,545703750829,2881,"End"
-2881,545703750829,3000,0,"End",545703753829,"[NULL]",545681794403,2884,"AsyncBegin"
-2884,545681794403,32652426,0,"AsyncBegin",545681794403,545681614403,545681805403,2884,"Begin"
-2884,545681805403,1000,0,"Begin",545681983403,545681614403,545681829403,2884,"STEP_SEND_INPUT_EVENT_UI"
-2884,545681829403,33000,0,"STEP_SEND_INPUT_EVENT_UI",545681983403,545681903611,545681906611,2884,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2884,545681906611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545681916611,545691798611,545691802611,2884,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2884,545691802611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545691839611,545693521611,545693521611,2884,"STEP_SWAP_BUFFERS"
-2884,545693521611,7000,0,"STEP_SWAP_BUFFERS",545693528611,545693969829,545693969829,2884,"STEP_DRAW_AND_SWAP"
-2884,545693969829,8000,0,"STEP_DRAW_AND_SWAP",545693977829,545714454829,545714454829,2884,"End"
-2884,545714454829,2000,0,"End",545714456829,"[NULL]",545691182403,2885,"AsyncBegin"
-2885,545691182403,34488426,0,"AsyncBegin",545691182403,545691819403,545691834403,2885,"Begin"
-2885,545691834403,2000,0,"Begin",545691925403,545691819403,545691874403,2885,"STEP_SEND_INPUT_EVENT_UI"
-2885,545691874403,47000,0,"STEP_SEND_INPUT_EVENT_UI",545691925403,545692055611,545692061611,2885,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2885,545692061611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545692073611,545703179611,545703184611,2885,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2885,545703184611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545703220611,545705806611,545705806611,2885,"STEP_SWAP_BUFFERS"
-2885,545705806611,7000,0,"STEP_SWAP_BUFFERS",545705813611,545706252829,545706252829,2885,"STEP_DRAW_AND_SWAP"
-2885,545706252829,7000,0,"STEP_DRAW_AND_SWAP",545706259829,545725677829,545725677829,2885,"End"
-2885,545725677829,2000,0,"End",545725679829,"[NULL]",545702355403,2886,"AsyncBegin"
-2886,545702355403,34887426,0,"AsyncBegin",545702355403,545703039403,545703056403,2886,"Begin"
-2886,545703056403,2000,0,"Begin",545703154403,545703039403,545703097403,2886,"STEP_SEND_INPUT_EVENT_UI"
-2886,545703097403,52000,0,"STEP_SEND_INPUT_EVENT_UI",545703154403,545703276611,545703300611,2886,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2886,545703300611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545703312611,545714437611,545714440611,2886,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2886,545714440611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545714481611,545716787611,545716787611,2886,"STEP_SWAP_BUFFERS"
-2886,545716787611,8000,0,"STEP_SWAP_BUFFERS",545716795611,545717228829,545717228829,2886,"STEP_DRAW_AND_SWAP"
-2886,545717228829,8000,0,"STEP_DRAW_AND_SWAP",545717236829,545737251829,545737251829,2886,"End"
-2886,545737251829,2000,0,"End",545737253829,"[NULL]",545713526403,2887,"AsyncBegin"
-2887,545713526403,34615426,0,"AsyncBegin",545713526403,545714310403,545714329403,2887,"Begin"
-2887,545714329403,3000,0,"Begin",545714583403,545714310403,545714375403,2887,"STEP_SEND_INPUT_EVENT_UI"
-2887,545714375403,201000,0,"STEP_SEND_INPUT_EVENT_UI",545714583403,545714639611,545714645611,2887,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2887,545714645611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545714657611,545726201611,545726206611,2887,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2887,545726206611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545726246611,545728218611,545728218611,2887,"STEP_SWAP_BUFFERS"
-2887,545728218611,8000,0,"STEP_SWAP_BUFFERS",545728226611,545728661829,545728661829,2887,"STEP_DRAW_AND_SWAP"
-2887,545728661829,8000,0,"STEP_DRAW_AND_SWAP",545728669829,545748149829,545748149829,2887,"End"
-2887,545748149829,2000,0,"End",545748151829,"[NULL]",545724697403,2888,"AsyncBegin"
-2888,545724697403,36799426,0,"AsyncBegin",545724697403,545725536403,545725554403,2888,"Begin"
-2888,545725554403,2000,0,"Begin",545725655403,545725536403,545725595403,2888,"STEP_SEND_INPUT_EVENT_UI"
-2888,545725595403,55000,0,"STEP_SEND_INPUT_EVENT_UI",545725655403,545726300611,545726305611,2888,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2888,545726305611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545726317611,545737740611,545737744611,2888,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2888,545737744611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545737782611,545739404611,545739404611,2888,"STEP_SWAP_BUFFERS"
-2888,545739404611,6000,0,"STEP_SWAP_BUFFERS",545739410611,545739832829,545739832829,2888,"STEP_DRAW_AND_SWAP"
-2888,545739832829,7000,0,"STEP_DRAW_AND_SWAP",545739839829,545761508829,545761508829,2888,"End"
-2888,545761508829,3000,0,"End",545761511829,"[NULL]",545735867403,2889,"AsyncBegin"
-2889,545735867403,35326426,0,"AsyncBegin",545735867403,545736697403,545736718403,2889,"Begin"
-2889,545736718403,2000,0,"Begin",545736833403,545736697403,545736765403,2889,"STEP_SEND_INPUT_EVENT_UI"
-2889,545736765403,62000,0,"STEP_SEND_INPUT_EVENT_UI",545736833403,545737847611,545737851611,2889,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2889,545737851611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545737864611,545747896611,545747901611,2889,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2889,545747901611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545747945611,545749570611,545749570611,2889,"STEP_SWAP_BUFFERS"
-2889,545749570611,6000,0,"STEP_SWAP_BUFFERS",545749576611,545749997829,545749997829,2889,"STEP_DRAW_AND_SWAP"
-2889,545749997829,6000,0,"STEP_DRAW_AND_SWAP",545750003829,545771200829,545771200829,2889,"End"
-2889,545771200829,2000,0,"End",545771202829,"[NULL]",545747040403,2890,"AsyncBegin"
-2890,545747040403,35047426,0,"AsyncBegin",545747040403,545748874403,545748889403,2890,"Begin"
-2890,545748889403,1000,0,"Begin",545749091403,545748874403,545748968403,2890,"STEP_SEND_INPUT_EVENT_UI"
-2890,545748968403,116000,0,"STEP_SEND_INPUT_EVENT_UI",545749091403,545749100611,545749108611,2890,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2890,545749108611,13000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545749123611,545759989611,545759993611,2890,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2890,545759993611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545760037611,545762422611,545762422611,2890,"STEP_SWAP_BUFFERS"
-2890,545762422611,7000,0,"STEP_SWAP_BUFFERS",545762429611,545762851829,545762851829,2890,"STEP_DRAW_AND_SWAP"
-2890,545762851829,6000,0,"STEP_DRAW_AND_SWAP",545762857829,545782095829,545782095829,2890,"End"
-2890,545782095829,3000,0,"End",545782098829,"[NULL]",545758211403,2891,"AsyncBegin"
-2891,545758211403,34990426,0,"AsyncBegin",545758211403,545759258403,545759276403,2891,"Begin"
-2891,545759276403,2000,0,"Begin",545759384403,545759258403,545759321403,2891,"STEP_SEND_INPUT_EVENT_UI"
-2891,545759321403,57000,0,"STEP_SEND_INPUT_EVENT_UI",545759384403,545760216611,545760222611,2891,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2891,545760222611,38000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545760266611,545770425611,545770429611,2891,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2891,545770429611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545770469611,545772129611,545772129611,2891,"STEP_SWAP_BUFFERS"
-2891,545772129611,6000,0,"STEP_SWAP_BUFFERS",545772135611,545772543829,545772543829,2891,"STEP_DRAW_AND_SWAP"
-2891,545772543829,6000,0,"STEP_DRAW_AND_SWAP",545772549829,545793208829,545793208829,2891,"End"
-2891,545793208829,2000,0,"End",545793210829,"[NULL]",545769381403,2892,"AsyncBegin"
-2892,545769381403,39529426,0,"AsyncBegin",545769381403,545770375403,545770396403,2892,"Begin"
-2892,545770396403,3000,0,"Begin",545770528403,545770375403,545770451403,2892,"STEP_SEND_INPUT_EVENT_UI"
-2892,545770451403,69000,0,"STEP_SEND_INPUT_EVENT_UI",545770528403,545771055611,545771063611,2892,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2892,545771063611,12000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545771077611,545781663611,545781667611,2892,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2892,545781667611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545781703611,545783314611,545783314611,2892,"STEP_SWAP_BUFFERS"
-2892,545783314611,6000,0,"STEP_SWAP_BUFFERS",545783320611,545783690829,545783690829,2892,"STEP_DRAW_AND_SWAP"
-2892,545783690829,6000,0,"STEP_DRAW_AND_SWAP",545783696829,545808924829,545808924829,2892,"End"
-2892,545808924829,3000,0,"End",545808927829,"[NULL]",545780550403,2893,"AsyncBegin"
-2893,545780550403,35967426,0,"AsyncBegin",545780550403,545782203403,545782218403,2893,"Begin"
-2893,545782218403,2000,0,"Begin",545782309403,545782203403,545782255403,2893,"STEP_SEND_INPUT_EVENT_UI"
-2893,545782255403,49000,0,"STEP_SEND_INPUT_EVENT_UI",545782309403,545782382611,545782389611,2893,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2893,545782389611,13000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545782404611,545792786611,545792790611,2893,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2893,545792790611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545792829611,545795262611,545795262611,2893,"STEP_SWAP_BUFFERS"
-2893,545795262611,7000,0,"STEP_SWAP_BUFFERS",545795269611,545796104829,545796104829,2893,"STEP_DRAW_AND_SWAP"
-2893,545796104829,9000,0,"STEP_DRAW_AND_SWAP",545796113829,545816526829,545816526829,2893,"End"
-2893,545816526829,2000,0,"End",545816528829,"[NULL]",545791721403,2894,"AsyncBegin"
-2894,545791721403,45468426,1,"AsyncBegin",545791721403,545792514403,545792536403,2894,"Begin"
-2894,545792536403,2000,1,"Begin",545792648403,545792514403,545792584403,2894,"STEP_SEND_INPUT_EVENT_UI"
-2894,545792584403,58000,1,"STEP_SEND_INPUT_EVENT_UI",545792648403,545792895611,545792900611,2894,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2894,545792900611,11000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",545792913611,545803896611,545803900611,2894,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2894,545803900611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545803940611,545817301611,545817301611,2894,"STEP_SWAP_BUFFERS"
-2894,545817301611,16000,1,"STEP_SWAP_BUFFERS",545817317611,545819176829,545819176829,2894,"STEP_DRAW_AND_SWAP"
-2894,545819176829,8000,1,"STEP_DRAW_AND_SWAP",545819184829,545837200829,545837200829,2894,"End"
-2894,545837200829,3000,1,"End",545837203829,"[NULL]",545802892403,2895,"AsyncBegin"
-2895,545802892403,45651426,1,"AsyncBegin",545802892403,545804221403,545804270403,2895,"Begin"
-2895,545804270403,2000,1,"Begin",545804390403,545804221403,545804322403,2895,"STEP_SEND_INPUT_EVENT_UI"
-2895,545804322403,61000,1,"STEP_SEND_INPUT_EVENT_UI",545804390403,545804452611,545804458611,2895,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2895,545804458611,11000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",545804470611,545817484611,545817486611,2895,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2895,545817486611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545817519611,545819202611,545819202611,2895,"STEP_SWAP_BUFFERS"
-2895,545819202611,6000,1,"STEP_SWAP_BUFFERS",545819208611,545826817829,545826817829,2895,"STEP_DRAW_AND_SWAP"
-2895,545826817829,7000,1,"STEP_DRAW_AND_SWAP",545826824829,545848551829,545848551829,2895,"End"
-2895,545848551829,2000,1,"End",545848553829,"[NULL]",545825234403,2897,"AsyncBegin"
-2897,545825234403,34662426,0,"AsyncBegin",545825234403,545826095403,545826110403,2897,"Begin"
-2897,545826110403,3000,0,"Begin",545826202403,545826095403,545826149403,2897,"STEP_SEND_INPUT_EVENT_UI"
-2897,545826149403,48000,0,"STEP_SEND_INPUT_EVENT_UI",545826202403,545826273611,545826281611,2897,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2897,545826281611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",545826294611,545842124611,545842129611,2897,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2897,545842129611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",545842170611,545844671611,545844671611,2897,"STEP_SWAP_BUFFERS"
-2897,545844671611,8000,0,"STEP_SWAP_BUFFERS",545844679611,545845554829,545845554829,2897,"STEP_DRAW_AND_SWAP"
-2897,545845554829,8000,0,"STEP_DRAW_AND_SWAP",545845562829,545859905829,545859905829,2897,"End"
-2897,545859905829,2000,0,"End",545859907829,"[NULL]",546027000403,2918,"AsyncBegin"
-2918,546027000403,24672426,0,"AsyncBegin",546027000403,546030704403,546031041403,2918,"Begin"
-2918,546031041403,2000,0,"Begin",546031129403,546030704403,546031099403,2918,"STEP_SEND_INPUT_EVENT_UI"
-2918,546031099403,22000,0,"STEP_SEND_INPUT_EVENT_UI",546031129403,546031763611,546031767611,2918,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2918,546031767611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546031780611,546032545611,546032548611,2918,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2918,546032548611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546032578611,546033504611,546033504611,2918,"STEP_SWAP_BUFFERS"
-2918,546033504611,7000,0,"STEP_SWAP_BUFFERS",546033511611,546036368829,546036368829,2918,"STEP_DRAW_AND_SWAP"
-2918,546036368829,9000,0,"STEP_DRAW_AND_SWAP",546036377829,546051706829,546051706829,2918,"End"
-2918,546051706829,8000,0,"End",546051714829,"[NULL]",546035000403,2920,"AsyncBegin"
-2920,546035000403,27274426,0,"AsyncBegin",546035000403,546036805403,546036957403,2920,"Begin"
-2920,546036957403,2000,0,"Begin",546037226403,546036805403,546037157403,2920,"STEP_SEND_INPUT_EVENT_UI"
-2920,546037157403,52000,0,"STEP_SEND_INPUT_EVENT_UI",546037226403,546037290611,546037297611,2920,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2920,546037297611,13000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546037312611,546038471611,546038475611,2920,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2920,546038475611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546038513611,546039413611,546039413611,2920,"STEP_SWAP_BUFFERS"
-2920,546039413611,7000,0,"STEP_SWAP_BUFFERS",546039420611,546041499829,546041499829,2920,"STEP_DRAW_AND_SWAP"
-2920,546041499829,10000,0,"STEP_DRAW_AND_SWAP",546041509829,546062279829,546062279829,2920,"End"
-2920,546062279829,2000,0,"End",546062281829,"[NULL]",546044000403,2922,"AsyncBegin"
-2922,546044000403,28587426,0,"AsyncBegin",546044000403,546045602403,546045753403,2922,"Begin"
-2922,546045753403,1000,0,"Begin",546045828403,546045602403,546045780403,2922,"STEP_SEND_INPUT_EVENT_UI"
-2922,546045780403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546045828403,546045909611,546045911611,2922,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2922,546045911611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546045924611,546049062611,546049066611,2922,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2922,546049066611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546049103611,546050028611,546050028611,2922,"STEP_SWAP_BUFFERS"
-2922,546050028611,7000,0,"STEP_SWAP_BUFFERS",546050035611,546056565829,546056565829,2922,"STEP_DRAW_AND_SWAP"
-2922,546056565829,10000,0,"STEP_DRAW_AND_SWAP",546056575829,546072594829,546072594829,2922,"End"
-2922,546072594829,2000,0,"End",546072596829,"[NULL]",546052000403,2924,"AsyncBegin"
-2924,546052000403,41821426,1,"AsyncBegin",546052000403,546057257403,546057389403,2924,"Begin"
-2924,546057389403,1000,1,"Begin",546057503403,546057257403,546057417403,2924,"STEP_SEND_INPUT_EVENT_UI"
-2924,546057417403,71000,1,"STEP_SEND_INPUT_EVENT_UI",546057503403,546057521611,546057523611,2924,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2924,546057523611,8000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",546057532611,546060136611,546060140611,2924,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2924,546060140611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546060176611,546060788611,546060788611,2924,"STEP_SWAP_BUFFERS"
-2924,546060788611,6000,1,"STEP_SWAP_BUFFERS",546060794611,546072983829,546072983829,2924,"STEP_DRAW_AND_SWAP"
-2924,546072983829,5000,1,"STEP_DRAW_AND_SWAP",546072988829,546093831829,546093831829,2924,"End"
-2924,546093831829,2000,1,"End",546093833829,"[NULL]",546060000403,2926,"AsyncBegin"
-2926,546060000403,44914426,1,"AsyncBegin",546060000403,546061893403,546062009403,2926,"Begin"
-2926,546062009403,1000,1,"Begin",546062077403,546061893403,546062034403,2926,"STEP_SEND_INPUT_EVENT_UI"
-2926,546062034403,32000,1,"STEP_SEND_INPUT_EVENT_UI",546062077403,546062104611,546062106611,2926,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2926,546062106611,9000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",546062116611,546071407611,546071410611,2926,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2926,546071410611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546071441611,546072109611,546072109611,2926,"STEP_SWAP_BUFFERS"
-2926,546072109611,6000,1,"STEP_SWAP_BUFFERS",546072115611,546084900829,546084900829,2926,"STEP_DRAW_AND_SWAP"
-2926,546084900829,2000,1,"STEP_DRAW_AND_SWAP",546084902829,546104917829,546104917829,2926,"End"
-2926,546104917829,1000,1,"End",546104918829,"[NULL]",546076000403,2930,"AsyncBegin"
-2930,546076000403,28902426,0,"AsyncBegin",546076000403,546078271403,546078414403,2930,"Begin"
-2930,546078414403,1000,0,"Begin",546078488403,546078271403,546078440403,2930,"STEP_SEND_INPUT_EVENT_UI"
-2930,546078440403,36000,0,"STEP_SEND_INPUT_EVENT_UI",546078488403,546078555611,546078558611,2930,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2930,546078558611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546078569611,546082555611,546082558611,2930,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2930,546082558611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546082596611,546083318611,546083318611,2930,"STEP_SWAP_BUFFERS"
-2930,546083318611,7000,0,"STEP_SWAP_BUFFERS",546083325611,546084891829,546084891829,2930,"STEP_DRAW_AND_SWAP"
-2930,546084891829,8000,0,"STEP_DRAW_AND_SWAP",546084899829,546104909829,546104909829,2930,"End"
-2930,546104909829,2000,0,"End",546104911829,"[NULL]",546085000403,2932,"AsyncBegin"
-2932,546085000403,31881426,0,"AsyncBegin",546085000403,546086197403,546086329403,2932,"Begin"
-2932,546086329403,1000,0,"Begin",546086403403,546086197403,546086356403,2932,"STEP_SEND_INPUT_EVENT_UI"
-2932,546086356403,34000,0,"STEP_SEND_INPUT_EVENT_UI",546086403403,546086444611,546086446611,2932,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2932,546086446611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546086456611,546094099611,546094103611,2932,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2932,546094103611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546094140611,546094733611,546094733611,2932,"STEP_SWAP_BUFFERS"
-2932,546094733611,6000,0,"STEP_SWAP_BUFFERS",546094739611,546096093829,546096093829,2932,"STEP_DRAW_AND_SWAP"
-2932,546096093829,8000,0,"STEP_DRAW_AND_SWAP",546096101829,546116889829,546116889829,2932,"End"
-2932,546116889829,2000,0,"End",546116891829,"[NULL]",546093000403,2934,"AsyncBegin"
-2934,546093000403,34989426,0,"AsyncBegin",546093000403,546094650403,546094776403,2934,"Begin"
-2934,546094776403,1000,0,"Begin",546094846403,546094650403,546094801403,2934,"STEP_SEND_INPUT_EVENT_UI"
-2934,546094801403,33000,0,"STEP_SEND_INPUT_EVENT_UI",546094846403,546095114611,546095119611,2934,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2934,546095119611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546095128611,546104611611,546104616611,2934,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2934,546104616611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546104651611,546105363611,546105363611,2934,"STEP_SWAP_BUFFERS"
-2934,546105363611,5000,0,"STEP_SWAP_BUFFERS",546105368611,546107001829,546107001829,2934,"STEP_DRAW_AND_SWAP"
-2934,546107001829,6000,0,"STEP_DRAW_AND_SWAP",546107007829,546127998829,546127998829,2934,"End"
-2934,546127998829,2000,0,"End",546128000829,"[NULL]",546109000403,2938,"AsyncBegin"
-2938,546109000403,41953426,1,"AsyncBegin",546109000403,546110931403,546111071403,2938,"Begin"
-2938,546111071403,1000,1,"Begin",546111154403,546110931403,546111100403,2938,"STEP_SEND_INPUT_EVENT_UI"
-2938,546111100403,40000,1,"STEP_SEND_INPUT_EVENT_UI",546111154403,546111216611,546111218611,2938,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2938,546111218611,8000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",546111227611,546116794611,546116798611,2938,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2938,546116798611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546116835611,546117666611,546117666611,2938,"STEP_SWAP_BUFFERS"
-2938,546117666611,6000,1,"STEP_SWAP_BUFFERS",546117672611,546130112829,546130112829,2938,"STEP_DRAW_AND_SWAP"
-2938,546130112829,1000,1,"STEP_DRAW_AND_SWAP",546130113829,546150956829,546150956829,2938,"End"
-2938,546150956829,1000,1,"End",546150957829,"[NULL]",546118000403,2940,"AsyncBegin"
-2940,546118000403,32872426,0,"AsyncBegin",546118000403,546119096403,546119389403,2940,"Begin"
-2940,546119389403,1000,0,"Begin",546119656403,546119096403,546119418403,2940,"STEP_SEND_INPUT_EVENT_UI"
-2940,546119418403,120000,0,"STEP_SEND_INPUT_EVENT_UI",546119656403,546119504611,546119508611,2940,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2940,546119508611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546119518611,546127524611,546127527611,2940,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2940,546127527611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546127561611,546128489611,546128489611,2940,"STEP_SWAP_BUFFERS"
-2940,546128489611,27000,0,"STEP_SWAP_BUFFERS",546128516611,546130104829,546130104829,2940,"STEP_DRAW_AND_SWAP"
-2940,546130104829,7000,0,"STEP_DRAW_AND_SWAP",546130111829,546150880829,546150880829,2940,"End"
-2940,546150880829,69000,0,"End",546150949829,"[NULL]",546126000403,2942,"AsyncBegin"
-2942,546126000403,35348426,0,"AsyncBegin",546126000403,546126954403,546128468403,2942,"Begin"
-2942,546128468403,1000,0,"Begin",546128599403,546126954403,546128503403,2942,"STEP_SEND_INPUT_EVENT_UI"
-2942,546128503403,78000,0,"STEP_SEND_INPUT_EVENT_UI",546128599403,546128618611,546128623611,2942,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2942,546128623611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546128633611,546139155611,546139160611,2942,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2942,546139160611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546139210611,546140019611,546140019611,2942,"STEP_SWAP_BUFFERS"
-2942,546140019611,5000,0,"STEP_SWAP_BUFFERS",546140024611,546141380829,546141380829,2942,"STEP_DRAW_AND_SWAP"
-2942,546141380829,9000,0,"STEP_DRAW_AND_SWAP",546141389829,546161356829,546161356829,2942,"End"
-2942,546161356829,2000,0,"End",546161358829,"[NULL]",546142000403,2946,"AsyncBegin"
-2946,546142000403,42106426,0,"AsyncBegin",546142000403,546143640403,546143776403,2946,"Begin"
-2946,546143776403,1000,0,"Begin",546143885403,546143640403,546143802403,2946,"STEP_SEND_INPUT_EVENT_UI"
-2946,546143802403,64000,0,"STEP_SEND_INPUT_EVENT_UI",546143885403,546143952611,546143956611,2946,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2946,546143956611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546143968611,546150338611,546150343611,2946,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2946,546150343611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546150382611,546152014611,546152014611,2946,"STEP_SWAP_BUFFERS"
-2946,546152014611,7000,0,"STEP_SWAP_BUFFERS",546152021611,546162653829,546162653829,2946,"STEP_DRAW_AND_SWAP"
-2946,546162653829,8000,0,"STEP_DRAW_AND_SWAP",546162661829,546184114829,546184114829,2946,"End"
-2946,546184114829,2000,0,"End",546184116829,"[NULL]",546150000403,2948,"AsyncBegin"
-2948,546150000403,45005426,1,"AsyncBegin",546150000403,546151950403,546152147403,2948,"Begin"
-2948,546152147403,1000,1,"Begin",546152222403,546151950403,546152174403,2948,"STEP_SEND_INPUT_EVENT_UI"
-2948,546152174403,36000,1,"STEP_SEND_INPUT_EVENT_UI",546152222403,546152273611,546152278611,2948,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2948,546152278611,9000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",546152288611,546161082611,546161087611,2948,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2948,546161087611,3000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546161130611,546162213611,546162213611,2948,"STEP_SWAP_BUFFERS"
-2948,546162213611,7000,1,"STEP_SWAP_BUFFERS",546162220611,546175298829,546175298829,2948,"STEP_DRAW_AND_SWAP"
-2948,546175298829,1000,1,"STEP_DRAW_AND_SWAP",546175299829,546195008829,546195008829,2948,"End"
-2948,546195008829,2000,1,"End",546195010829,"[NULL]",546159000403,2950,"AsyncBegin"
-2950,546159000403,35994426,0,"AsyncBegin",546159000403,546161262403,546161396403,2950,"Begin"
-2950,546161396403,1000,0,"Begin",546161473403,546161262403,546161423403,2950,"STEP_SEND_INPUT_EVENT_UI"
-2950,546161423403,36000,0,"STEP_SEND_INPUT_EVENT_UI",546161473403,546161629611,546161632611,2950,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2950,546161632611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546161641611,546172303611,546172307611,2950,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2950,546172307611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546172429611,546173523611,546173523611,2950,"STEP_SWAP_BUFFERS"
-2950,546173523611,8000,0,"STEP_SWAP_BUFFERS",546173531611,546175282829,546175282829,2950,"STEP_DRAW_AND_SWAP"
-2950,546175282829,15000,0,"STEP_DRAW_AND_SWAP",546175297829,546195000829,546195000829,2950,"End"
-2950,546195000829,3000,0,"End",546195003829,"[NULL]",546175000403,2954,"AsyncBegin"
-2954,546175000403,30970426,0,"AsyncBegin",546175000403,546176663403,546176812403,2954,"Begin"
-2954,546176812403,1000,0,"Begin",546176884403,546176663403,546176838403,2954,"STEP_SEND_INPUT_EVENT_UI"
-2954,546176838403,34000,0,"STEP_SEND_INPUT_EVENT_UI",546176884403,546176948611,546176951611,2954,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2954,546176951611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546176961611,546183503611,546183508611,2954,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2954,546183508611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546183547611,546184802611,546184802611,2954,"STEP_SWAP_BUFFERS"
-2954,546184802611,7000,0,"STEP_SWAP_BUFFERS",546184809611,546186327829,546186327829,2954,"STEP_DRAW_AND_SWAP"
-2954,546186327829,8000,0,"STEP_DRAW_AND_SWAP",546186335829,546205976829,546205976829,2954,"End"
-2954,546205976829,2000,0,"End",546205978829,"[NULL]",546183000403,2956,"AsyncBegin"
-2956,546183000403,45256426,1,"AsyncBegin",546183000403,546186878403,546186997403,2956,"Begin"
-2956,546186997403,1000,1,"Begin",546187103403,546186878403,546187022403,2956,"STEP_SEND_INPUT_EVENT_UI"
-2956,546187022403,66000,1,"STEP_SEND_INPUT_EVENT_UI",546187103403,546187138611,546187140611,2956,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2956,546187140611,8000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",546187149611,546194427611,546194430611,2956,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2956,546194430611,2000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546194464611,546195772611,546195772611,2956,"STEP_SWAP_BUFFERS"
-2956,546195772611,6000,1,"STEP_SWAP_BUFFERS",546195778611,546207402829,546207402829,2956,"STEP_DRAW_AND_SWAP"
-2956,546207402829,7000,1,"STEP_DRAW_AND_SWAP",546207409829,546228297829,546228297829,2956,"End"
-2956,546228297829,7000,1,"End",546228304829,"[NULL]",546200000403,2960,"AsyncBegin"
-2960,546200000403,40097426,0,"AsyncBegin",546200000403,546201377403,546201519403,2960,"Begin"
-2960,546201519403,1000,0,"Begin",546201586403,546201377403,546201544403,2960,"STEP_SEND_INPUT_EVENT_UI"
-2960,546201544403,31000,0,"STEP_SEND_INPUT_EVENT_UI",546201586403,546201665611,546201667611,2960,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2960,546201667611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546201677611,546205643611,546205647611,2960,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2960,546205647611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546205696611,546206945611,546206945611,2960,"STEP_SWAP_BUFFERS"
-2960,546206945611,8000,0,"STEP_SWAP_BUFFERS",546206953611,546220078829,546220078829,2960,"STEP_DRAW_AND_SWAP"
-2960,546220078829,1000,0,"STEP_DRAW_AND_SWAP",546220079829,546240099829,546240099829,2960,"End"
-2960,546240099829,1000,0,"End",546240100829,"[NULL]",546208000403,2962,"AsyncBegin"
-2962,546208000403,32086426,0,"AsyncBegin",546208000403,546209350403,546209483403,2962,"Begin"
-2962,546209483403,1000,0,"Begin",546209547403,546209350403,546209508403,2962,"STEP_SEND_INPUT_EVENT_UI"
-2962,546209508403,29000,0,"STEP_SEND_INPUT_EVENT_UI",546209547403,546209595611,546209597611,2962,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2962,546209597611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546209606611,546217074611,546217078611,2962,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2962,546217078611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546217117611,546219522611,546219522611,2962,"STEP_SWAP_BUFFERS"
-2962,546219522611,6000,0,"STEP_SWAP_BUFFERS",546219528611,546220068829,546220068829,2962,"STEP_DRAW_AND_SWAP"
-2962,546220068829,8000,0,"STEP_DRAW_AND_SWAP",546220076829,546240093829,546240093829,2962,"End"
-2962,546240093829,2000,0,"End",546240095829,"[NULL]",546216000403,2964,"AsyncBegin"
-2964,546216000403,34686426,0,"AsyncBegin",546216000403,546217643403,546217768403,2964,"Begin"
-2964,546217768403,1000,0,"Begin",546217868403,546217643403,546217821403,2964,"STEP_SEND_INPUT_EVENT_UI"
-2964,546217821403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546217868403,546217917611,546217920611,2964,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2964,546217920611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546217930611,546228051611,546228054611,2964,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2964,546228054611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546228091611,546230585611,546230585611,2964,"STEP_SWAP_BUFFERS"
-2964,546230585611,9000,0,"STEP_SWAP_BUFFERS",546230594611,546230999829,546230999829,2964,"STEP_DRAW_AND_SWAP"
-2964,546230999829,7000,0,"STEP_DRAW_AND_SWAP",546231006829,546250694829,546250694829,2964,"End"
-2964,546250694829,2000,0,"End",546250696829,"[NULL]",546233000403,2968,"AsyncBegin"
-2968,546233000403,28852426,0,"AsyncBegin",546233000403,546234475403,546234614403,2968,"Begin"
-2968,546234614403,1000,0,"Begin",546234681403,546234475403,546234639403,2968,"STEP_SEND_INPUT_EVENT_UI"
-2968,546234639403,32000,0,"STEP_SEND_INPUT_EVENT_UI",546234681403,546234720611,546234723611,2968,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2968,546234723611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546234734611,546239796611,546239800611,2968,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2968,546239800611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546239846611,546241573611,546241573611,2968,"STEP_SWAP_BUFFERS"
-2968,546241573611,7000,0,"STEP_SWAP_BUFFERS",546241580611,546241964829,546241964829,2968,"STEP_DRAW_AND_SWAP"
-2968,546241964829,7000,0,"STEP_DRAW_AND_SWAP",546241971829,546261861829,546261861829,2968,"End"
-2968,546261861829,2000,0,"End",546261863829,"[NULL]",546241000403,2970,"AsyncBegin"
-2970,546241000403,32494426,0,"AsyncBegin",546241000403,546243029403,546243175403,2970,"Begin"
-2970,546243175403,1000,0,"Begin",546243308403,546243029403,546243234403,2970,"STEP_SEND_INPUT_EVENT_UI"
-2970,546243234403,39000,0,"STEP_SEND_INPUT_EVENT_UI",546243308403,546243388611,546243394611,2970,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2970,546243394611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546243407611,546250667611,546250672611,2970,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2970,546250672611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546250734611,546252948611,546252948611,2970,"STEP_SWAP_BUFFERS"
-2970,546252948611,8000,0,"STEP_SWAP_BUFFERS",546252956611,546253408829,546253408829,2970,"STEP_DRAW_AND_SWAP"
-2970,546253408829,8000,0,"STEP_DRAW_AND_SWAP",546253416829,546273503829,546273503829,2970,"End"
-2970,546273503829,2000,0,"End",546273505829,"[NULL]",546249000403,2972,"AsyncBegin"
-2972,546249000403,37304426,0,"AsyncBegin",546249000403,546250918403,546251050403,2972,"Begin"
-2972,546251050403,1000,0,"Begin",546251118403,546250918403,546251077403,2972,"STEP_SEND_INPUT_EVENT_UI"
-2972,546251077403,29000,0,"STEP_SEND_INPUT_EVENT_UI",546251118403,546251144611,546251146611,2972,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2972,546251146611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546251156611,546262000611,546262004611,2972,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2972,546262004611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546262046611,546263899611,546263899611,2972,"STEP_SWAP_BUFFERS"
-2972,546263899611,8000,0,"STEP_SWAP_BUFFERS",546263907611,546264307829,546264307829,2972,"STEP_DRAW_AND_SWAP"
-2972,546264307829,7000,0,"STEP_DRAW_AND_SWAP",546264314829,546286312829,546286312829,2972,"End"
-2972,546286312829,2000,0,"End",546286314829,"[NULL]",546265000403,2976,"AsyncBegin"
-2976,546265000403,32101426,0,"AsyncBegin",546265000403,546266881403,546267025403,2976,"Begin"
-2976,546267025403,31000,0,"Begin",546267136403,546266881403,546267087403,2976,"STEP_SEND_INPUT_EVENT_UI"
-2976,546267087403,36000,0,"STEP_SEND_INPUT_EVENT_UI",546267136403,546267229611,546267235611,2976,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2976,546267235611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546267248611,546273055611,546273059611,2976,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2976,546273059611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546273180611,546275260611,546275260611,2976,"STEP_SWAP_BUFFERS"
-2976,546275260611,8000,0,"STEP_SWAP_BUFFERS",546275268611,546275663829,546275663829,2976,"STEP_DRAW_AND_SWAP"
-2976,546275663829,8000,0,"STEP_DRAW_AND_SWAP",546275671829,546297108829,546297108829,2976,"End"
-2976,546297108829,3000,0,"End",546297111829,"[NULL]",546273000403,2978,"AsyncBegin"
-2978,546273000403,34156426,0,"AsyncBegin",546273000403,546275484403,546275607403,2978,"Begin"
-2978,546275607403,1000,0,"Begin",546276344403,546275484403,546275633403,2978,"STEP_SEND_INPUT_EVENT_UI"
-2978,546275633403,690000,0,"STEP_SEND_INPUT_EVENT_UI",546276344403,546275715611,546275719611,2978,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2978,546275719611,5000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546275726611,546283860611,546283863611,2978,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2978,546283863611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546283902611,546285767611,546285767611,2978,"STEP_SWAP_BUFFERS"
-2978,546285767611,7000,0,"STEP_SWAP_BUFFERS",546285774611,546286878829,546286878829,2978,"STEP_DRAW_AND_SWAP"
-2978,546286878829,5000,0,"STEP_DRAW_AND_SWAP",546286883829,546307163829,546307163829,2978,"End"
-2978,546307163829,2000,0,"End",546307165829,"[NULL]",546290000403,2982,"AsyncBegin"
-2982,546290000403,27915426,0,"AsyncBegin",546290000403,546291566403,546291911403,2982,"Begin"
-2982,546291911403,2000,0,"Begin",546291983403,546291566403,546291939403,2982,"STEP_SEND_INPUT_EVENT_UI"
-2982,546291939403,33000,0,"STEP_SEND_INPUT_EVENT_UI",546291983403,546292037611,546292042611,2982,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2982,546292042611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546292053611,546295022611,546295026611,2982,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2982,546295026611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546295062611,546296953611,546296953611,2982,"STEP_SWAP_BUFFERS"
-2982,546296953611,7000,0,"STEP_SWAP_BUFFERS",546296960611,546297448829,546297448829,2982,"STEP_DRAW_AND_SWAP"
-2982,546297448829,4000,0,"STEP_DRAW_AND_SWAP",546297452829,546317924829,546317924829,2982,"End"
-2982,546317924829,2000,0,"End",546317926829,"[NULL]",546298000403,2984,"AsyncBegin"
-2984,546298000403,30723426,0,"AsyncBegin",546298000403,546299971403,546300114403,2984,"Begin"
-2984,546300114403,1000,0,"Begin",546300180403,546299971403,546300138403,2984,"STEP_SEND_INPUT_EVENT_UI"
-2984,546300138403,31000,0,"STEP_SEND_INPUT_EVENT_UI",546300180403,546300219611,546300220611,2984,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2984,546300220611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546300230611,546306555611,546306559611,2984,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2984,546306559611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546306598611,546308592611,546308592611,2984,"STEP_SWAP_BUFFERS"
-2984,546308592611,5000,0,"STEP_SWAP_BUFFERS",546308597611,546308994829,546308994829,2984,"STEP_DRAW_AND_SWAP"
-2984,546308994829,7000,0,"STEP_DRAW_AND_SWAP",546309001829,546328731829,546328731829,2984,"End"
-2984,546328731829,2000,0,"End",546328733829,"[NULL]",546307000403,2986,"AsyncBegin"
-2986,546307000403,32918426,0,"AsyncBegin",546307000403,546308149403,546308285403,2986,"Begin"
-2986,546308285403,2000,0,"Begin",546308356403,546308149403,546308311403,2986,"STEP_SEND_INPUT_EVENT_UI"
-2986,546308311403,34000,0,"STEP_SEND_INPUT_EVENT_UI",546308356403,546308444611,546308446611,2986,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2986,546308446611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546308454611,546317470611,546317474611,2986,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2986,546317474611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546317526611,546319206611,546319206611,2986,"STEP_SWAP_BUFFERS"
-2986,546319206611,8000,0,"STEP_SWAP_BUFFERS",546319214611,546319620829,546319620829,2986,"STEP_DRAW_AND_SWAP"
-2986,546319620829,7000,0,"STEP_DRAW_AND_SWAP",546319627829,546339929829,546339929829,2986,"End"
-2986,546339929829,3000,0,"End",546339932829,"[NULL]",546323000403,2990,"AsyncBegin"
-2990,546323000403,29800426,0,"AsyncBegin",546323000403,546324513403,546324666403,2990,"Begin"
-2990,546324666403,2000,0,"Begin",546324737403,546324513403,546324693403,2990,"STEP_SEND_INPUT_EVENT_UI"
-2990,546324693403,32000,0,"STEP_SEND_INPUT_EVENT_UI",546324737403,546324784611,546324786611,2990,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2990,546324786611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546324796611,546328619611,546328624611,2990,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2990,546328624611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546328668611,546330703611,546330703611,2990,"STEP_SWAP_BUFFERS"
-2990,546330703611,33000,0,"STEP_SWAP_BUFFERS",546330736611,546331260829,546331260829,2990,"STEP_DRAW_AND_SWAP"
-2990,546331260829,8000,0,"STEP_DRAW_AND_SWAP",546331268829,546352807829,546352807829,2990,"End"
-2990,546352807829,3000,0,"End",546352810829,"[NULL]",546331000403,2992,"AsyncBegin"
-2992,546331000403,31314426,0,"AsyncBegin",546331000403,546332697403,546333011403,2992,"Begin"
-2992,546333011403,2000,0,"Begin",546333088403,546332697403,546333039403,2992,"STEP_SEND_INPUT_EVENT_UI"
-2992,546333039403,38000,0,"STEP_SEND_INPUT_EVENT_UI",546333088403,546333139611,546333146611,2992,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2992,546333146611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546333158611,546340189611,546340193611,2992,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2992,546340193611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546340229611,546342849611,546342849611,2992,"STEP_SWAP_BUFFERS"
-2992,546342849611,6000,0,"STEP_SWAP_BUFFERS",546342855611,546343276829,546343276829,2992,"STEP_DRAW_AND_SWAP"
-2992,546343276829,25000,0,"STEP_DRAW_AND_SWAP",546343301829,546362325829,546362325829,2992,"End"
-2992,546362325829,2000,0,"End",546362327829,"[NULL]",546339000403,2994,"AsyncBegin"
-2994,546339000403,35092426,0,"AsyncBegin",546339000403,546340778403,546341033403,2994,"Begin"
-2994,546341033403,2000,0,"Begin",546341105403,546340778403,546341060403,2994,"STEP_SEND_INPUT_EVENT_UI"
-2994,546341060403,34000,0,"STEP_SEND_INPUT_EVENT_UI",546341105403,546341145611,546341151611,2994,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2994,546341151611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546341161611,546350884611,546350887611,2994,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2994,546350887611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546350991611,546352902611,546352902611,2994,"STEP_SWAP_BUFFERS"
-2994,546352902611,7000,0,"STEP_SWAP_BUFFERS",546352909611,546353440829,546353440829,2994,"STEP_DRAW_AND_SWAP"
-2994,546353440829,5000,0,"STEP_DRAW_AND_SWAP",546353445829,546374102829,546374102829,2994,"End"
-2994,546374102829,2000,0,"End",546374104829,"[NULL]",546356000403,2998,"AsyncBegin"
-2998,546356000403,28702426,0,"AsyncBegin",546356000403,546357505403,546357671403,2998,"Begin"
-2998,546357671403,2000,0,"Begin",546357755403,546357505403,546357704403,2998,"STEP_SEND_INPUT_EVENT_UI"
-2998,546357704403,37000,0,"STEP_SEND_INPUT_EVENT_UI",546357755403,546357777611,546357779611,2998,"STEP_HANDLE_INPUT_EVENT_IMPL"
-2998,546357779611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546357788611,546362651611,546362655611,2998,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-2998,546362655611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546362697611,546364468611,546364468611,2998,"STEP_SWAP_BUFFERS"
-2998,546364468611,9000,0,"STEP_SWAP_BUFFERS",546364477611,546364896829,546364896829,2998,"STEP_DRAW_AND_SWAP"
-2998,546364896829,8000,0,"STEP_DRAW_AND_SWAP",546364904829,546384825829,546384825829,2998,"End"
-2998,546384825829,109000,0,"End",546384934829,"[NULL]",546364000403,3000,"AsyncBegin"
-3000,546364000403,32457426,0,"AsyncBegin",546364000403,546365563403,546365752403,3000,"Begin"
-3000,546365752403,1000,0,"Begin",546365833403,546365563403,546365781403,3000,"STEP_SEND_INPUT_EVENT_UI"
-3000,546365781403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546365833403,546366021611,546366023611,3000,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3000,546366023611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546366034611,546373564611,546373568611,3000,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3000,546373568611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546373614611,546376356611,546376356611,3000,"STEP_SWAP_BUFFERS"
-3000,546376356611,6000,0,"STEP_SWAP_BUFFERS",546376362611,546376832829,546376832829,3000,"STEP_DRAW_AND_SWAP"
-3000,546376832829,7000,0,"STEP_DRAW_AND_SWAP",546376839829,546396465829,546396465829,3000,"End"
-3000,546396465829,3000,0,"End",546396468829,"[NULL]",546372000403,3002,"AsyncBegin"
-3002,546372000403,35043426,0,"AsyncBegin",546372000403,546374588403,546374732403,3002,"Begin"
-3002,546374732403,1000,0,"Begin",546374803403,546374588403,546374760403,3002,"STEP_SEND_INPUT_EVENT_UI"
-3002,546374760403,31000,0,"STEP_SEND_INPUT_EVENT_UI",546374803403,546374837611,546374839611,3002,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3002,546374839611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546374848611,546384434611,546384437611,3002,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3002,546384437611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546384477611,546386153611,546386153611,3002,"STEP_SWAP_BUFFERS"
-3002,546386153611,7000,0,"STEP_SWAP_BUFFERS",546386160611,546386698829,546386698829,3002,"STEP_DRAW_AND_SWAP"
-3002,546386698829,6000,0,"STEP_DRAW_AND_SWAP",546386704829,546407050829,546407050829,3002,"End"
-3002,546407050829,2000,0,"End",546407052829,"[NULL]",546389000403,3006,"AsyncBegin"
-3006,546389000403,29285426,0,"AsyncBegin",546389000403,546390565403,546390760403,3006,"Begin"
-3006,546390760403,2000,0,"Begin",546390845403,546390565403,546390790403,3006,"STEP_SEND_INPUT_EVENT_UI"
-3006,546390790403,40000,0,"STEP_SEND_INPUT_EVENT_UI",546390845403,546390891611,546390894611,3006,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3006,546390894611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546390905611,546396335611,546396340611,3006,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3006,546396340611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546396384611,546398059611,546398059611,3006,"STEP_SWAP_BUFFERS"
-3006,546398059611,7000,0,"STEP_SWAP_BUFFERS",546398066611,546398466829,546398466829,3006,"STEP_DRAW_AND_SWAP"
-3006,546398466829,8000,0,"STEP_DRAW_AND_SWAP",546398474829,546418293829,546418293829,3006,"End"
-3006,546418293829,2000,0,"End",546418295829,"[NULL]",546397000403,3008,"AsyncBegin"
-3008,546397000403,32831426,0,"AsyncBegin",546397000403,546398582403,546398711403,3008,"Begin"
-3008,546398711403,1000,0,"Begin",546398780403,546398582403,546398736403,3008,"STEP_SEND_INPUT_EVENT_UI"
-3008,546398736403,32000,0,"STEP_SEND_INPUT_EVENT_UI",546398780403,546399217611,546399219611,3008,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3008,546399219611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546399228611,546406876611,546406881611,3008,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3008,546406881611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546407869611,546409583611,546409583611,3008,"STEP_SWAP_BUFFERS"
-3008,546409583611,7000,0,"STEP_SWAP_BUFFERS",546409590611,546410078829,546410078829,3008,"STEP_DRAW_AND_SWAP"
-3008,546410078829,7000,0,"STEP_DRAW_AND_SWAP",546410085829,546429839829,546429839829,3008,"End"
-3008,546429839829,3000,0,"End",546429842829,"[NULL]",546405000403,3010,"AsyncBegin"
-3010,546405000403,35630426,0,"AsyncBegin",546405000403,546407326403,546407543403,3010,"Begin"
-3010,546407543403,2000,0,"Begin",546407626403,546407326403,546407575403,3010,"STEP_SEND_INPUT_EVENT_UI"
-3010,546407575403,38000,0,"STEP_SEND_INPUT_EVENT_UI",546407626403,546408025611,546408028611,3010,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3010,546408028611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546408037611,546417901611,546417904611,3010,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3010,546417904611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546417944611,546420009611,546420009611,3010,"STEP_SWAP_BUFFERS"
-3010,546420009611,11000,0,"STEP_SWAP_BUFFERS",546420020611,546420431829,546420431829,3010,"STEP_DRAW_AND_SWAP"
-3010,546420431829,7000,0,"STEP_DRAW_AND_SWAP",546420438829,546440637829,546440637829,3010,"End"
-3010,546440637829,2000,0,"End",546440639829,"[NULL]",546422000403,3014,"AsyncBegin"
-3014,546422000403,30119426,0,"AsyncBegin",546422000403,546423149403,546423316403,3014,"Begin"
-3014,546423316403,2000,0,"Begin",546423392403,546423149403,546423343403,3014,"STEP_SEND_INPUT_EVENT_UI"
-3014,546423343403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546423392403,546423418611,546423420611,3014,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3014,546423420611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546423428611,546429153611,546429158611,3014,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3014,546429158611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546429196611,546431932611,546431932611,3014,"STEP_SWAP_BUFFERS"
-3014,546431932611,6000,0,"STEP_SWAP_BUFFERS",546431938611,546432346829,546432346829,3014,"STEP_DRAW_AND_SWAP"
-3014,546432346829,7000,0,"STEP_DRAW_AND_SWAP",546432353829,546452126829,546452126829,3014,"End"
-3014,546452126829,2000,0,"End",546452128829,"[NULL]",546430000403,3016,"AsyncBegin"
-3016,546430000403,33185426,0,"AsyncBegin",546430000403,546431264403,546431405403,3016,"Begin"
-3016,546431405403,1000,0,"Begin",546431480403,546431264403,546431431403,3016,"STEP_SEND_INPUT_EVENT_UI"
-3016,546431431403,37000,0,"STEP_SEND_INPUT_EVENT_UI",546431480403,546431519611,546431522611,3016,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3016,546431522611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546431533611,546441188611,546441191611,3016,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3016,546441191611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546441224611,546443045611,546443045611,3016,"STEP_SWAP_BUFFERS"
-3016,546443045611,6000,0,"STEP_SWAP_BUFFERS",546443051611,546443544829,546443544829,3016,"STEP_DRAW_AND_SWAP"
-3016,546443544829,7000,0,"STEP_DRAW_AND_SWAP",546443551829,546463194829,546463194829,3016,"End"
-3016,546463194829,2000,0,"End",546463196829,"[NULL]",546446000403,3020,"AsyncBegin"
-3020,546446000403,28386426,0,"AsyncBegin",546446000403,546447951403,546448098403,3020,"Begin"
-3020,546448098403,1000,0,"Begin",546448169403,546447951403,546448124403,3020,"STEP_SEND_INPUT_EVENT_UI"
-3020,546448124403,33000,0,"STEP_SEND_INPUT_EVENT_UI",546448169403,546448219611,546448222611,3020,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3020,546448222611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546448231611,546451329611,546451333611,3020,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3020,546451333611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546451372611,546454220611,546454220611,3020,"STEP_SWAP_BUFFERS"
-3020,546454220611,9000,0,"STEP_SWAP_BUFFERS",546454229611,546454674829,546454674829,3020,"STEP_DRAW_AND_SWAP"
-3020,546454674829,7000,0,"STEP_DRAW_AND_SWAP",546454681829,546474393829,546474393829,3020,"End"
-3020,546474393829,3000,0,"End",546474396829,"[NULL]",546455000403,3022,"AsyncBegin"
-3022,546455000403,30102426,0,"AsyncBegin",546455000403,546456215403,546456359403,3022,"Begin"
-3022,546456359403,1000,0,"Begin",546456428403,546456215403,546456384403,3022,"STEP_SEND_INPUT_EVENT_UI"
-3022,546456384403,32000,0,"STEP_SEND_INPUT_EVENT_UI",546456428403,546456461611,546456463611,3022,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3022,546456463611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546456472611,546462961611,546462965611,3022,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3022,546462965611,1000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546463005611,546465098611,546465098611,3022,"STEP_SWAP_BUFFERS"
-3022,546465098611,6000,0,"STEP_SWAP_BUFFERS",546465104611,546465524829,546465524829,3022,"STEP_DRAW_AND_SWAP"
-3022,546465524829,8000,0,"STEP_DRAW_AND_SWAP",546465532829,546485110829,546485110829,3022,"End"
-3022,546485110829,2000,0,"End",546485112829,"[NULL]",546463000403,3024,"AsyncBegin"
-3024,546463000403,33512426,0,"AsyncBegin",546463000403,546464373403,546464518403,3024,"Begin"
-3024,546464518403,1000,0,"Begin",546464595403,546464373403,546464544403,3024,"STEP_SEND_INPUT_EVENT_UI"
-3024,546464544403,37000,0,"STEP_SEND_INPUT_EVENT_UI",546464595403,546464703611,546464705611,3024,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3024,546464705611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546464715611,546473824611,546473827611,3024,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3024,546473827611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546473862611,546475568611,546475568611,3024,"STEP_SWAP_BUFFERS"
-3024,546475568611,8000,0,"STEP_SWAP_BUFFERS",546475576611,546476008829,546476008829,3024,"STEP_DRAW_AND_SWAP"
-3024,546476008829,8000,0,"STEP_DRAW_AND_SWAP",546476016829,546496519829,546496519829,3024,"End"
-3024,546496519829,2000,0,"End",546496521829,"[NULL]",546479000403,3028,"AsyncBegin"
-3028,546479000403,28455426,0,"AsyncBegin",546479000403,546480721403,546480874403,3028,"Begin"
-3028,546480874403,2000,0,"Begin",546480950403,546480721403,546480902403,3028,"STEP_SEND_INPUT_EVENT_UI"
-3028,546480902403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546480950403,546481026611,546481028611,3028,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3028,546481028611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546481041611,546485007611,546485011611,3028,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3028,546485011611,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546485059611,546487385611,546487385611,3028,"STEP_SWAP_BUFFERS"
-3028,546487385611,8000,0,"STEP_SWAP_BUFFERS",546487393611,546487986829,546487986829,3028,"STEP_DRAW_AND_SWAP"
-3028,546487986829,8000,0,"STEP_DRAW_AND_SWAP",546487994829,546507462829,546507462829,3028,"End"
-3028,546507462829,3000,0,"End",546507465829,"[NULL]",546488000403,3030,"AsyncBegin"
-3030,546488000403,30791426,0,"AsyncBegin",546488000403,546489074403,546489211403,3030,"Begin"
-3030,546489211403,2000,0,"Begin",546489275403,546489074403,546489236403,3030,"STEP_SEND_INPUT_EVENT_UI"
-3030,546489236403,28000,0,"STEP_SEND_INPUT_EVENT_UI",546489275403,546489489611,546489491611,3030,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3030,546489491611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546489499611,546496435611,546496440611,3030,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3030,546496440611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546496481611,546498136611,546498136611,3030,"STEP_SWAP_BUFFERS"
-3030,546498136611,5000,0,"STEP_SWAP_BUFFERS",546498141611,546498528829,546498528829,3030,"STEP_DRAW_AND_SWAP"
-3030,546498528829,6000,0,"STEP_DRAW_AND_SWAP",546498534829,546518802829,546518802829,3030,"End"
-3030,546518802829,1000,0,"End",546518803829,"[NULL]",546496000403,3032,"AsyncBegin"
-3032,546496000403,34105426,0,"AsyncBegin",546496000403,546497219403,546497345403,3032,"Begin"
-3032,546497345403,1000,0,"Begin",546497413403,546497219403,546497371403,3032,"STEP_SEND_INPUT_EVENT_UI"
-3032,546497371403,30000,0,"STEP_SEND_INPUT_EVENT_UI",546497413403,546497439611,546497441611,3032,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3032,546497441611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546497450611,546507298611,546507302611,3032,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3032,546507302611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546507342611,546509375611,546509375611,3032,"STEP_SWAP_BUFFERS"
-3032,546509375611,7000,0,"STEP_SWAP_BUFFERS",546509382611,546510189829,546510189829,3032,"STEP_DRAW_AND_SWAP"
-3032,546510189829,9000,0,"STEP_DRAW_AND_SWAP",546510198829,546530114829,546530114829,3032,"End"
-3032,546530114829,2000,0,"End",546530116829,"[NULL]",546512000403,3036,"AsyncBegin"
-3036,546512000403,29329426,0,"AsyncBegin",546512000403,546513858403,546514007403,3036,"Begin"
-3036,546514007403,2000,0,"Begin",546514080403,546513858403,546514036403,3036,"STEP_SEND_INPUT_EVENT_UI"
-3036,546514036403,32000,0,"STEP_SEND_INPUT_EVENT_UI",546514080403,546514160611,546514163611,3036,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3036,546514163611,11000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546514176611,546519116611,546519120611,3036,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3036,546519120611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546519156611,546521220611,546521220611,3036,"STEP_SWAP_BUFFERS"
-3036,546521220611,8000,0,"STEP_SWAP_BUFFERS",546521228611,546521662829,546521662829,3036,"STEP_DRAW_AND_SWAP"
-3036,546521662829,8000,0,"STEP_DRAW_AND_SWAP",546521670829,546541338829,546541338829,3036,"End"
-3036,546541338829,2000,0,"End",546541340829,"[NULL]",546520000403,3038,"AsyncBegin"
-3038,546520000403,32321426,0,"AsyncBegin",546520000403,546522038403,546522186403,3038,"Begin"
-3038,546522186403,2000,0,"Begin",546522274403,546522038403,546522222403,3038,"STEP_SEND_INPUT_EVENT_UI"
-3038,546522222403,39000,0,"STEP_SEND_INPUT_EVENT_UI",546522274403,546522327611,546522330611,3038,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3038,546522330611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546522339611,546529785611,546529790611,3038,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3038,546529790611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546529836611,546532477611,546532477611,3038,"STEP_SWAP_BUFFERS"
-3038,546532477611,8000,0,"STEP_SWAP_BUFFERS",546532485611,546532942829,546532942829,3038,"STEP_DRAW_AND_SWAP"
-3038,546532942829,8000,0,"STEP_DRAW_AND_SWAP",546532950829,546552358829,546552358829,3038,"End"
-3038,546552358829,9000,0,"End",546552367829,"[NULL]",546529000403,3040,"AsyncBegin"
-3040,546529000403,34457426,0,"AsyncBegin",546529000403,546530169403,546530324403,3040,"Begin"
-3040,546530324403,1000,0,"Begin",546530399403,546530169403,546530352403,3040,"STEP_SEND_INPUT_EVENT_UI"
-3040,546530352403,33000,0,"STEP_SEND_INPUT_EVENT_UI",546530399403,546530540611,546530542611,3040,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3040,546530542611,12000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546530557611,546540823611,546540826611,3040,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3040,546540826611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546541737611,546543749611,546543749611,3040,"STEP_SWAP_BUFFERS"
-3040,546543749611,8000,0,"STEP_SWAP_BUFFERS",546543757611,546544204829,546544204829,3040,"STEP_DRAW_AND_SWAP"
-3040,546544204829,8000,0,"STEP_DRAW_AND_SWAP",546544212829,546563463829,546563463829,3040,"End"
-3040,546563463829,3000,0,"End",546563466829,"[NULL]",546545000403,3044,"AsyncBegin"
-3044,546545000403,29668426,0,"AsyncBegin",546545000403,546546602403,546546816403,3044,"Begin"
-3044,546546816403,1000,0,"Begin",546546890403,546546602403,546546844403,3044,"STEP_SEND_INPUT_EVENT_UI"
-3044,546546844403,34000,0,"STEP_SEND_INPUT_EVENT_UI",546546890403,546546951611,546546953611,3044,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3044,546546953611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546546963611,546552344611,546552349611,3044,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3044,546552349611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546552400611,546554385611,546554385611,3044,"STEP_SWAP_BUFFERS"
-3044,546554385611,8000,0,"STEP_SWAP_BUFFERS",546554393611,546555748829,546555748829,3044,"STEP_DRAW_AND_SWAP"
-3044,546555748829,7000,0,"STEP_DRAW_AND_SWAP",546555755829,546574677829,546574677829,3044,"End"
-3044,546574677829,2000,0,"End",546574679829,"[NULL]",546553000403,3046,"AsyncBegin"
-3046,546553000403,32830426,0,"AsyncBegin",546553000403,546554885403,546555031403,3046,"Begin"
-3046,546555031403,2000,0,"Begin",546555128403,546554885403,546555060403,3046,"STEP_SEND_INPUT_EVENT_UI"
-3046,546555060403,29000,0,"STEP_SEND_INPUT_EVENT_UI",546555128403,546555422611,546555425611,3046,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3046,546555425611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546555434611,546563185611,546563189611,3046,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3046,546563189611,1000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546563228611,546565411611,546565411611,3046,"STEP_SWAP_BUFFERS"
-3046,546565411611,8000,0,"STEP_SWAP_BUFFERS",546565419611,546565832829,546565832829,3046,"STEP_DRAW_AND_SWAP"
-3046,546565832829,8000,0,"STEP_DRAW_AND_SWAP",546565840829,546585839829,546585839829,3046,"End"
-3046,546585839829,2000,0,"End",546585841829,"[NULL]",546561000403,3048,"AsyncBegin"
-3048,546561000403,35849426,0,"AsyncBegin",546561000403,546562758403,546562888403,3048,"Begin"
-3048,546562888403,2000,0,"Begin",546562956403,546562758403,546562915403,3048,"STEP_SEND_INPUT_EVENT_UI"
-3048,546562915403,30000,0,"STEP_SEND_INPUT_EVENT_UI",546562956403,546563366611,546563369611,3048,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3048,546563369611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546563376611,546574498611,546574502611,3048,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3048,546574502611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546574540611,546576468611,546576468611,3048,"STEP_SWAP_BUFFERS"
-3048,546576468611,7000,0,"STEP_SWAP_BUFFERS",546576475611,546576952829,546576952829,3048,"STEP_DRAW_AND_SWAP"
-3048,546576952829,7000,0,"STEP_DRAW_AND_SWAP",546576959829,546596855829,546596855829,3048,"End"
-3048,546596855829,2000,0,"End",546596857829,"[NULL]",546578000403,3052,"AsyncBegin"
-3052,546578000403,30365426,0,"AsyncBegin",546578000403,546579536403,546579683403,3052,"Begin"
-3052,546579683403,1000,0,"Begin",546579801403,546579536403,546579740403,3052,"STEP_SEND_INPUT_EVENT_UI"
-3052,546579740403,45000,0,"STEP_SEND_INPUT_EVENT_UI",546579801403,546579837611,546579841611,3052,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3052,546579841611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546579852611,546585857611,546585861611,3052,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3052,546585861611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546585911611,546588384611,546588384611,3052,"STEP_SWAP_BUFFERS"
-3052,546588384611,5000,0,"STEP_SWAP_BUFFERS",546588389611,546588821829,546588821829,3052,"STEP_DRAW_AND_SWAP"
-3052,546588821829,8000,0,"STEP_DRAW_AND_SWAP",546588829829,546608373829,546608373829,3052,"End"
-3052,546608373829,2000,0,"End",546608375829,"[NULL]",546586000403,3054,"AsyncBegin"
-3054,546586000403,33666426,0,"AsyncBegin",546586000403,546587765403,546587909403,3054,"Begin"
-3054,546587909403,2000,0,"Begin",546587983403,546587765403,546587936403,3054,"STEP_SEND_INPUT_EVENT_UI"
-3054,546587936403,35000,0,"STEP_SEND_INPUT_EVENT_UI",546587983403,546588218611,546588223611,3054,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3054,546588223611,8000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546588233611,546597078611,546597082611,3054,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3054,546597082611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546597117611,546599028611,546599028611,3054,"STEP_SWAP_BUFFERS"
-3054,546599028611,7000,0,"STEP_SWAP_BUFFERS",546599035611,546599458829,546599458829,3054,"STEP_DRAW_AND_SWAP"
-3054,546599458829,6000,0,"STEP_DRAW_AND_SWAP",546599464829,546619678829,546619678829,3054,"End"
-3054,546619678829,3000,0,"End",546619681829,"[NULL]",546594000403,3056,"AsyncBegin"
-3056,546594000403,36913426,0,"AsyncBegin",546594000403,546596575403,546596755403,3056,"Begin"
-3056,546596755403,1000,0,"Begin",546596834403,546596575403,546596782403,3056,"STEP_SEND_INPUT_EVENT_UI"
-3056,546596782403,39000,0,"STEP_SEND_INPUT_EVENT_UI",546596834403,546597253611,546597255611,3056,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3056,546597255611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546597263611,546608211611,546608216611,3056,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3056,546608216611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546608259611,546609939611,546609939611,3056,"STEP_SWAP_BUFFERS"
-3056,546609939611,30000,0,"STEP_SWAP_BUFFERS",546609969611,546610374829,546610374829,3056,"STEP_DRAW_AND_SWAP"
-3056,546610374829,14000,0,"STEP_DRAW_AND_SWAP",546610388829,546630922829,546630922829,3056,"End"
-3056,546630922829,2000,0,"End",546630924829,"[NULL]",546611000403,3060,"AsyncBegin"
-3060,546611000403,30855426,0,"AsyncBegin",546611000403,546612047403,546612188403,3060,"Begin"
-3060,546612188403,1000,0,"Begin",546612256403,546612047403,546612214403,3060,"STEP_SEND_INPUT_EVENT_UI"
-3060,546612214403,31000,0,"STEP_SEND_INPUT_EVENT_UI",546612256403,546612302611,546612305611,3060,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3060,546612305611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546612317611,546620167611,546620171611,3060,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3060,546620171611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546620269611,546622281611,546622281611,3060,"STEP_SWAP_BUFFERS"
-3060,546622281611,7000,0,"STEP_SWAP_BUFFERS",546622288611,546622725829,546622725829,3060,"STEP_DRAW_AND_SWAP"
-3060,546622725829,8000,0,"STEP_DRAW_AND_SWAP",546622733829,546641865829,546641865829,3060,"End"
-3060,546641865829,3000,0,"End",546641868829,"[NULL]",546619000403,3062,"AsyncBegin"
-3062,546619000403,33897426,0,"AsyncBegin",546619000403,546620384403,546620518403,3062,"Begin"
-3062,546620518403,1000,0,"Begin",546620591403,546620384403,546620548403,3062,"STEP_SEND_INPUT_EVENT_UI"
-3062,546620548403,31000,0,"STEP_SEND_INPUT_EVENT_UI",546620591403,546620608611,546620611611,3062,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3062,546620611611,6000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546620618611,546630379611,546630384611,3062,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3062,546630384611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546630421611,546632167611,546632167611,3062,"STEP_SWAP_BUFFERS"
-3062,546632167611,8000,0,"STEP_SWAP_BUFFERS",546632175611,546632600829,546632600829,3062,"STEP_DRAW_AND_SWAP"
-3062,546632600829,7000,0,"STEP_DRAW_AND_SWAP",546632607829,546652905829,546652905829,3062,"End"
-3062,546652905829,3000,0,"End",546652908829,"[NULL]",546627000403,3064,"AsyncBegin"
-3064,546627000403,36941426,0,"AsyncBegin",546627000403,546629888403,546630054403,3064,"Begin"
-3064,546630054403,1000,0,"Begin",546630174403,546629888403,546630083403,3064,"STEP_SEND_INPUT_EVENT_UI"
-3064,546630083403,76000,0,"STEP_SEND_INPUT_EVENT_UI",546630174403,546630538611,546630540611,3064,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3064,546630540611,7000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546630548611,546642123611,546642128611,3064,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3064,546642128611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546642161611,546643979611,546643979611,3064,"STEP_SWAP_BUFFERS"
-3064,546643979611,7000,0,"STEP_SWAP_BUFFERS",546643986611,546644451829,546644451829,3064,"STEP_DRAW_AND_SWAP"
-3064,546644451829,7000,0,"STEP_DRAW_AND_SWAP",546644458829,546663948829,546663948829,3064,"End"
-3064,546663948829,2000,0,"End",546663950829,"[NULL]",546644000403,3068,"AsyncBegin"
-3068,546644000403,31194426,0,"AsyncBegin",546644000403,546645017403,546645164403,3068,"Begin"
-3068,546645164403,1000,0,"Begin",546645251403,546645017403,546645192403,3068,"STEP_SEND_INPUT_EVENT_UI"
-3068,546645192403,45000,0,"STEP_SEND_INPUT_EVENT_UI",546645251403,546645343611,546645345611,3068,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3068,546645345611,9000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546645356611,546653047611,546653050611,3068,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3068,546653050611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546653084611,546655933611,546655933611,3068,"STEP_SWAP_BUFFERS"
-3068,546655933611,5000,0,"STEP_SWAP_BUFFERS",546655938611,546656344829,546656344829,3068,"STEP_DRAW_AND_SWAP"
-3068,546656344829,8000,0,"STEP_DRAW_AND_SWAP",546656352829,546675205829,546675205829,3068,"End"
-3068,546675205829,2000,0,"End",546675207829,"[NULL]",546652000403,3070,"AsyncBegin"
-3070,546652000403,34276426,0,"AsyncBegin",546652000403,546653717403,546653856403,3070,"Begin"
-3070,546653856403,2000,0,"Begin",546653957403,546653717403,546653911403,3070,"STEP_SEND_INPUT_EVENT_UI"
-3070,546653911403,33000,0,"STEP_SEND_INPUT_EVENT_UI",546653957403,546654006611,546654013611,3070,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3070,546654013611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546654025611,546663767611,546663770611,3070,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3070,546663770611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546663811611,546666007611,546666007611,3070,"STEP_SWAP_BUFFERS"
-3070,546666007611,8000,0,"STEP_SWAP_BUFFERS",546666015611,546666425829,546666425829,3070,"STEP_DRAW_AND_SWAP"
-3070,546666425829,8000,0,"STEP_DRAW_AND_SWAP",546666433829,546686287829,546686287829,3070,"End"
-3070,546686287829,3000,0,"End",546686290829,"[NULL]",546676000403,3074,"AsyncBegin"
-3074,546676000403,32746426,0,"AsyncBegin",546676000403,546677976403,546678120403,3074,"Begin"
-3074,546678120403,1000,0,"Begin",546678325403,546677976403,546678271403,3074,"STEP_SEND_INPUT_EVENT_UI"
-3074,546678271403,40000,0,"STEP_SEND_INPUT_EVENT_UI",546678325403,546678362611,546678365611,3074,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3074,546678365611,10000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546678377611,546691500611,546691505611,3074,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3074,546691505611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546691548611,546693461611,546693461611,3074,"STEP_SWAP_BUFFERS"
-3074,546693461611,7000,0,"STEP_SWAP_BUFFERS",546693468611,546693912829,546693912829,3074,"STEP_DRAW_AND_SWAP"
-3074,546693912829,7000,0,"STEP_DRAW_AND_SWAP",546693919829,546708755829,546708755829,3074,"End"
-3074,546708755829,3000,0,"End",546708758829,"[NULL]",546701627403,3077,"AsyncBegin"
-3077,546701627403,29680426,0,"AsyncBegin",546701627403,546701412403,546701638403,3077,"Begin"
-3077,546701638403,1000,0,"Begin",546701829403,546701412403,546701662403,3077,"STEP_SEND_INPUT_EVENT_UI"
-3077,546701662403,36000,0,"STEP_SEND_INPUT_EVENT_UI",546701829403,546701751611,546701754611,3077,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3077,546701754611,12000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546701768611,546713886611,546713890611,3077,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3077,546713890611,3000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546713932611,546715795611,546715795611,3077,"STEP_SWAP_BUFFERS"
-3077,546715795611,2000,0,"STEP_SWAP_BUFFERS",546715797611,546716289829,546716289829,3077,"STEP_DRAW_AND_SWAP"
-3077,546716289829,1000,0,"STEP_DRAW_AND_SWAP",546716290829,546731310829,546731310829,3077,"End"
-3077,546731310829,1000,0,"End",546731311829,"[NULL]",546718977403,3079,"AsyncBegin"
-3079,546718977403,34597426,0,"AsyncBegin",546718977403,546720104403,546720121403,3079,"Begin"
-3079,546720121403,2000,0,"Begin",546720221403,546720104403,546720162403,3079,"STEP_SEND_INPUT_EVENT_UI"
-3079,546720162403,55000,0,"STEP_SEND_INPUT_EVENT_UI",546720221403,546720297611,546720307611,3079,"STEP_HANDLE_INPUT_EVENT_IMPL"
-3079,546720307611,15000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",546720324611,546735889611,546735893611,3079,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-3079,546735893611,2000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546735932611,546736765611,546736765611,3079,"STEP_SWAP_BUFFERS"
-3079,546736765611,6000,0,"STEP_SWAP_BUFFERS",546736771611,546737248829,546737248829,3079,"STEP_DRAW_AND_SWAP"
-3079,546737248829,8000,0,"STEP_DRAW_AND_SWAP",546737256829,546753582829,546753582829,3079,"End"
-3079,546753582829,2000,0,"End",546753584829,"[NULL]","[NULL]","[NULL]","[NULL]"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event_general_validation.out b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event_general_validation.out
deleted file mode 100644
index 5a223bf..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event_general_validation.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"total_scroll_updates","total_flow_event_steps","total_janky_flow_event_steps","number_of_unique_steps"
-139,1112,56,8
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event_queuing_delay.out b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event_queuing_delay.out
deleted file mode 100644
index 519e25c..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event_queuing_delay.out
+++ /dev/null
@@ -1,26 +0,0 @@
-
-"trace_id","jank","step","next_step","ancestor_end","maybe_next_ancestor_ts","queuing_time_ns"
-2954,0,"AsyncBegin","Begin",546175000403,546176663403,1663000
-2954,0,"Begin","STEP_SEND_INPUT_EVENT_UI",546176884403,546176663403,0
-2954,0,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",546176884403,546176948611,64208
-2954,0,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546176961611,546183503611,6542000
-2954,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_SWAP_BUFFERS",546183547611,546184802611,1255000
-2954,0,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",546184809611,546186327829,1518218
-2954,0,"STEP_DRAW_AND_SWAP","End",546186335829,546205976829,19641000
-2954,0,"End","AsyncBegin",546205978829,"[NULL]","[NULL]"
-2956,1,"AsyncBegin","Begin",546183000403,546186878403,3878000
-2956,1,"Begin","STEP_SEND_INPUT_EVENT_UI",546187103403,546186878403,0
-2956,1,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",546187103403,546187138611,35208
-2956,1,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546187149611,546194427611,7278000
-2956,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_SWAP_BUFFERS",546194464611,546195772611,1308000
-2956,1,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",546195778611,546207402829,11624218
-2956,1,"STEP_DRAW_AND_SWAP","End",546207409829,546228297829,20888000
-2956,1,"End","AsyncBegin",546228304829,"[NULL]","[NULL]"
-2960,0,"AsyncBegin","Begin",546200000403,546201377403,1377000
-2960,0,"Begin","STEP_SEND_INPUT_EVENT_UI",546201586403,546201377403,0
-2960,0,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",546201586403,546201665611,79208
-2960,0,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",546201677611,546205643611,3966000
-2960,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_SWAP_BUFFERS",546205696611,546206945611,1249000
-2960,0,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",546206953611,546220078829,13125218
-2960,0,"STEP_DRAW_AND_SWAP","End",546220079829,546240099829,20020000
-2960,0,"End","AsyncBegin",546240100829,"[NULL]","[NULL]"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event_queuing_delay_general_validation_test.sql b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event_queuing_delay_general_validation_test.sql
deleted file mode 100644
index 195e055..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_flow_event_queuing_delay_general_validation_test.sql
+++ /dev/null
@@ -1,28 +0,0 @@
--- Copyright 2023 The Chromium Authors
--- Use of this source code is governed by a BSD-style license that can be
--- found in the LICENSE file.
-SELECT RUN_METRIC('chrome/scroll_flow_event_queuing_delay.sql');
-
-SELECT
-  -- Each trace_id (in our example trace not true in general) has 8 steps. There
-  -- are 139 scrolls. So we expect 1112 rows in total 72 of which are janky.
-  (
-    SELECT
-      COUNT(*)
-    FROM (
-      SELECT
-        trace_id,
-        COUNT(*)
-      FROM scroll_flow_event_queuing_delay
-      GROUP BY trace_id
-    )
-  ) AS total_scroll_updates,
-  (
-    SELECT COUNT(*) FROM scroll_flow_event_queuing_delay
-  ) AS total_flow_event_steps,
-  (
-    SELECT COUNT(*) FROM scroll_flow_event_queuing_delay WHERE jank
-  ) AS total_janky_flow_event_steps,
-  (
-    SELECT COUNT(*) FROM (SELECT step FROM scroll_flow_event_queuing_delay GROUP BY step)
-  ) AS number_of_unique_steps;
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank.out b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank.out
deleted file mode 100644
index 163727e4..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank.out
+++ /dev/null
@@ -1,141 +0,0 @@
-
-"gesture_scroll_id","trace_id","jank","ts","dur","jank_budget"
-2708,2709,0,544958000403,19009426,-11933333.350000
-2708,2711,0,544966000403,22609426,-4733333.350000
-2708,2715,0,544983000403,28089426,-2853333.350000
-2708,2717,0,544991000403,30714426,-5708333.350000
-2708,2719,0,544999000403,34740426,-4307333.350000
-2708,2721,0,545007000403,37462426,-2760333.350000
-2708,2725,0,545024000403,31889426,-320333.350000
-2708,2727,0,545032000403,23876426,-12773333.350000
-2708,2729,0,545040000403,28316426,-2637333.350000
-2708,2733,0,545056000403,22620426,-9355333.350000
-2708,2735,0,545065000403,23642426,-3707333.350000
-2708,2739,0,545081000403,19016426,-11808333.350000
-2708,2741,0,545089000403,22491426,-4858333.350000
-2708,2743,0,545098000403,24940426,-2758333.350000
-2708,2747,0,545114000403,19365426,-11597333.350000
-2708,2749,0,545122000403,22629426,-3373333.350000
-2708,2753,0,545139000403,17669426,-11605333.350000
-2708,2755,0,545147000403,20941426,-5061333.350000
-2708,2757,0,545155000403,23321426,-3597333.350000
-2708,2761,0,545172000403,18585426,-12178333.350000
-2708,2763,0,545180000403,22430426,-4488333.350000
-2708,2765,0,545188000403,23545426,-3903333.350000
-2708,2769,0,545204000403,19115426,-10325333.350000
-2708,2771,0,545213000403,21107426,-6341333.350000
-2708,2773,0,545221000403,25065426,-3332333.350000
-2708,2777,0,545237000403,20064426,-10459333.350000
-2708,2779,0,545246000403,22190426,-2778333.350000
-2708,2783,0,545262000403,16635426,-11624333.350000
-2708,2785,0,545270000403,19926426,-5042333.350000
-2708,2787,0,545278000403,23003426,-2499333.350000
-2708,2791,0,545295000403,17169426,-11790333.350000
-2708,2793,0,545303000403,20626426,-4876333.350000
-2708,2795,0,545311000403,23560426,-2964333.350000
-2708,2799,0,545328000403,18191426,-11053333.350000
-2708,2801,0,545336000403,20911426,-5613333.350000
-2708,2803,0,545344000403,24228426,-2294333.350000
-2708,2807,0,545361000403,18189426,-11523333.350000
-2708,2809,0,545369000403,21379426,-5143333.350000
-2708,2811,0,545377000403,24913426,-2091333.350000
-2708,2815,0,545394000403,18671426,-11590333.350000
-2708,2817,0,545402000403,21928426,-3659333.350000
-2708,2821,0,545418000403,17254426,-11486333.350000
-2708,2823,0,545426000403,20407426,-5180333.350000
-2708,2825,0,545435000403,22633426,-6107333.350000
-2708,2827,0,545443000403,27179426,-1729333.350000
-2708,2831,0,545459000403,20575426,-11247333.350000
-2708,2833,0,545468000403,23489426,-3121333.350000
-2708,2837,0,545484000403,18277426,-11705333.350000
-2708,2839,0,545492000403,21649426,-4961333.350000
-2708,2841,0,545500000403,24734426,-2423333.350000
-2708,2845,0,545517000403,18824426,-11852333.350000
-2708,2847,0,545525000403,22343426,-4814333.350000
-2708,2849,0,545533000403,25222426,-2262333.350000
-2708,2853,0,545550000403,19151426,-11842333.350000
-2708,2855,0,545558000403,22660426,-3276333.350000
-2708,2859,0,545574000403,17603426,-10338333.350000
-2708,2861,0,545583000403,19608426,-6328333.350000
-2708,2863,0,545591000403,22822426,-3516333.350000
-2708,2867,0,545607000403,18005426,-11391333.350000
-2708,2869,0,545615000403,21063426,-5275333.350000
-2708,2871,0,545624000403,23894426,-3050333.350000
-2708,2875,0,545640000403,18611426,-11481333.350000
-2708,2877,0,545648000403,21759426,-5185333.350000
-2708,2879,0,545656000403,25004426,-5088333.350000
-2708,2881,0,545671000403,32742426,-595333.350000
-2708,2884,0,545681794403,32652426,-8423333.350000
-2708,2885,0,545691182403,34488426,-6497333.350000
-2708,2886,0,545702355403,34887426,-7934333.350000
-2708,2887,0,545713526403,34615426,-8605333.350000
-2708,2888,0,545724697403,36799426,-6149333.350000
-2708,2889,0,545735867403,35326426,-8054333.350000
-2708,2890,0,545747040403,35047426,-8276333.350000
-2708,2891,0,545758211403,34990426,-8390333.350000
-2708,2892,0,545769381403,39529426,-3794333.350000
-2708,2893,0,545780550403,35967426,-11895333.350000
-2708,2894,1,545791721403,45468426,1167666.650000
-2708,2895,1,545802892403,45651426,2655666.650000
-2708,2897,0,545825234403,34662426,1656666.650000
-2917,2918,0,546027000403,24672426,-10935333.350000
-2917,2920,0,546035000403,27274426,-5731333.350000
-2917,2922,0,546044000403,28587426,-7020333.350000
-2917,2924,1,546052000403,41821426,4900666.650000
-2917,2926,1,546060000403,44914426,7678666.650000
-2917,2930,0,546076000403,28902426,-11312333.350000
-2917,2932,0,546085000403,31881426,-5354333.350000
-2917,2934,0,546093000403,34989426,-5225333.350000
-2917,2938,1,546109000403,41953426,747666.650000
-2917,2940,0,546118000403,32872426,-10809333.350000
-2917,2942,0,546126000403,35348426,-5857333.350000
-2917,2946,0,546142000403,42106426,-1575333.350000
-2917,2948,1,546150000403,45005426,677666.650000
-2917,2950,0,546159000403,35994426,-3309333.350000
-2917,2954,0,546175000403,30970426,-13357333.350000
-2917,2956,1,546183000403,45256426,5952666.650000
-2917,2960,0,546200000403,40097426,-322333.350000
-2917,2962,0,546208000403,32086426,-10933333.350000
-2917,2964,0,546216000403,34686426,-2499333.350000
-2917,2968,0,546233000403,28852426,-11975333.350000
-2917,2970,0,546241000403,32494426,-4691333.350000
-2917,2972,0,546249000403,37304426,-3130333.350000
-2917,2976,0,546265000403,32101426,-10388333.350000
-2917,2978,0,546273000403,34156426,-2092333.350000
-2917,2982,0,546290000403,27915426,-11141333.350000
-2917,2984,0,546298000403,30723426,-5525333.350000
-2917,2986,0,546307000403,32918426,-5215333.350000
-2917,2990,0,546323000403,29800426,-9847333.350000
-2917,2992,0,546331000403,31314426,-6819333.350000
-2917,2994,0,546339000403,35092426,-1943333.350000
-2917,2998,0,546356000403,28702426,-12088333.350000
-2917,3000,0,546364000403,32457426,-4578333.350000
-2917,3002,0,546372000403,35043426,-2575333.350000
-2917,3006,0,546389000403,29285426,-11879333.350000
-2917,3008,0,546397000403,32831426,-4787333.350000
-2917,3010,0,546405000403,35630426,-2822333.350000
-2917,3014,0,546422000403,30119426,-11399333.350000
-2917,3016,0,546430000403,33185426,-3534333.350000
-2917,3020,0,546446000403,28386426,-10049333.350000
-2917,3022,0,546455000403,30102426,-6617333.350000
-2917,3024,0,546463000403,33512426,-3276333.350000
-2917,3028,0,546479000403,28455426,-10669333.350000
-2917,3030,0,546488000403,30791426,-5997333.350000
-2917,3032,0,546496000403,34105426,-3557333.350000
-2917,3036,0,546512000403,29329426,-11325333.350000
-2917,3038,0,546520000403,32321426,-5341333.350000
-2917,3040,0,546529000403,34457426,-3544333.350000
-2917,3044,0,546545000403,29668426,-11495333.350000
-2917,3046,0,546553000403,32830426,-5171333.350000
-2917,3048,0,546561000403,35849426,-2849333.350000
-2917,3052,0,546578000403,30365426,-11634333.350000
-2917,3054,0,546586000403,33666426,-5032333.350000
-2917,3056,0,546594000403,36913426,-2275333.350000
-2917,3060,0,546611000403,30855426,-11375333.350000
-2917,3062,0,546619000403,33897426,-5291333.350000
-2917,3064,0,546627000403,36941426,-2586333.350000
-2917,3068,0,546644000403,31194426,-11415333.350000
-2917,3070,0,546652000403,34276426,-5251333.350000
-2917,3074,0,546676000403,32746426,-5267333.350000
-2917,3077,0,546701627403,29680426,-11399333.350000
-2917,3079,0,546718977403,34597426,-3416333.350000
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_cause_queuing_delay.out b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_cause_queuing_delay.out
deleted file mode 100644
index a54d9b95..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_cause_queuing_delay.out
+++ /dev/null
@@ -1,25 +0,0 @@
-
-"process_name","thread_name","trace_id","jank","dur_overlapping_ns","metric_name"
-"Browser","CrProcessMain",2918,0,55000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.GestureProvider::OnTouchEvent"
-"Browser","CrProcessMain",2918,0,433000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.RenderWidgetHostImpl::ForwardTouchEvent-PassthroughTouchEventQueue::QueueEvent-InputRouterImpl::FilterAndSendWebInputEvent-LatencyInfo.Flow"
-"Renderer","Compositor",2918,0,66000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-LatencyInfo.Flow-WidgetInputHandlerManager::DidHandleInputEventSentToCompositor-MainThreadEventQueue::HandleEvent"
-"Renderer","Compositor",2918,0,116000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchEvent-LatencyInfo.Flow-InputHandlerProxy::HandleGestureScrollBegin-WidgetInputHandlerManager::DidHandleInputEventSentToCompositor"
-"Renderer","Compositor",2918,0,29000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-LatencyInfo.Flow-WidgetInputHandlerManager::DidHandleInputEventSentToCompositor-MainThreadEventQueue::HandleEvent"
-"Renderer","Compositor",2918,0,7000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.ScrollPredictor::ResampleScrollEvents"
-"Renderer","Compositor",2918,0,25000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.InputHandlerProxy::HandleGestureScrollUpdate-DeltaUnits"
-"Renderer","Compositor",2918,0,6000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2918,0,10000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.LatencyInfo.Flow"
-"Browser","CrProcessMain",2926,1,52000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.InputRouterImpl::GestureEventHandled-GestureEventQueue::ProcessGestureAck"
-"Browser","CrProcessMain",2926,1,17000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.GestureProvider::OnTouchEvent"
-"Renderer","Compositor",2926,1,1208,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-LatencyInfo.Flow"
-"Renderer","Compositor",2926,1,38000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-LatencyInfo.Flow"
-"Renderer","Compositor",2926,1,21000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchEvent-LatencyInfo.Flow-EventWithCallback::CoalesceWith"
-"Renderer","Compositor",2926,1,6000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.ScrollPredictor::ResampleScrollEvents"
-"Renderer","Compositor",2926,1,30000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.InputHandlerProxy::HandleGestureScrollUpdate-DeltaUnits"
-"Renderer","Compositor",2926,1,14000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerManager::DidHandleInputEventSentToCompositor-LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,2000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,5000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,8000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,2000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,8000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,2000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_cause_queuing_delay_general_validation.out b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_cause_queuing_delay_general_validation.out
deleted file mode 100644
index daf9c40..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_cause_queuing_delay_general_validation.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"total","janky_latency_info_non_jank_avg_dur","non_janky_latency_info_non_jank_avg_dur"
-139,6185.000000,6185.000000
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_cause_queuing_delay_restricted.out b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_cause_queuing_delay_restricted.out
deleted file mode 100644
index 4049795..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_cause_queuing_delay_restricted.out
+++ /dev/null
@@ -1,25 +0,0 @@
-
-"process_name","thread_name","trace_id","jank","dur_overlapping_ns","restricted_metric_name"
-"Browser","CrProcessMain",2918,0,55000,"QueuingDelay.NoJank.BlockingTasksUs.GestureProvider::OnTouchEvent"
-"Browser","CrProcessMain",2918,0,433000,"QueuingDelay.NoJank.BlockingTasksUs.RenderWidgetHostImpl::ForwardTouchEvent-UnknownEvent"
-"Renderer","Compositor",2918,0,66000,"QueuingDelay.NoJank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-UnknownEvent"
-"Renderer","Compositor",2918,0,116000,"QueuingDelay.NoJank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchEvent-UnknownEvent"
-"Renderer","Compositor",2918,0,29000,"QueuingDelay.NoJank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-UnknownEvent"
-"Renderer","Compositor",2918,0,7000,"QueuingDelay.NoJank.BlockingTasksUs.ScrollPredictor::ResampleScrollEvents"
-"Renderer","Compositor",2918,0,25000,"QueuingDelay.NoJank.BlockingTasksUs.InputHandlerProxy::HandleGestureScrollUpdate-UnknownEvent"
-"Renderer","Compositor",2918,0,6000,"QueuingDelay.NoJank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2918,0,10000,"QueuingDelay.NoJank.BlockingTasksUs.LatencyInfo.Flow"
-"Browser","CrProcessMain",2926,1,52000,"QueuingDelay.Jank.BlockingTasksUs.InputRouterImpl::GestureEventHandled-UnknownEvent"
-"Browser","CrProcessMain",2926,1,17000,"QueuingDelay.Jank.BlockingTasksUs.GestureProvider::OnTouchEvent"
-"Renderer","Compositor",2926,1,1208,"QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-UnknownEvent"
-"Renderer","Compositor",2926,1,38000,"QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchNonBlockingEvent-UnknownEvent"
-"Renderer","Compositor",2926,1,21000,"QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerImpl::DispatchEvent-UnknownEvent"
-"Renderer","Compositor",2926,1,6000,"QueuingDelay.Jank.BlockingTasksUs.ScrollPredictor::ResampleScrollEvents"
-"Renderer","Compositor",2926,1,30000,"QueuingDelay.Jank.BlockingTasksUs.InputHandlerProxy::HandleGestureScrollUpdate-UnknownEvent"
-"Renderer","Compositor",2926,1,14000,"QueuingDelay.Jank.BlockingTasksUs.WidgetInputHandlerManager::DidHandleInputEventSentToCompositor-UnknownEvent"
-"Gpu","VizCompositorThread",2926,1,2000,"QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,5000,"QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,8000,"QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,2000,"QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,8000,"QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
-"Gpu","VizCompositorThread",2926,1,2000,"QueuingDelay.Jank.BlockingTasksUs.LatencyInfo.Flow"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_general_validation.out b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_general_validation.out
deleted file mode 100644
index d76d3bc..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_general_validation.out
+++ /dev/null
@@ -1,3 +0,0 @@
-
-"total","scroll_dur","non_coalesced_updates","non_coalesced_dur","non_coalesced_janky_updates","non_coalesced_janky_dur","janky_percentage","avg_vsync_interval"
-2,1628470852,139,3974685214,7,310070982,7,16666666.666667
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_general_validation_test.sql b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_general_validation_test.sql
deleted file mode 100644
index 9f6d147..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_general_validation_test.sql
+++ /dev/null
@@ -1,70 +0,0 @@
--- Copyright 2023 The Chromium Authors
--- Use of this source code is governed by a BSD-style license that can be
--- found in the LICENSE file.
-
-SELECT RUN_METRIC('chrome/scroll_jank.sql');
-
-SELECT (
-  -- There are only two valid scrolls (one additional scroll is missing a begin
-  -- and the other is missing an end).
-  SELECT COUNT(*) FROM joined_scroll_begin_and_end
-) AS total,
-(
-  -- Of the two valid scrolls
-  -- gesture_scroll_id: 2708
-  --     starts at: 544958000403
-  --     ends at:   545859896829
-  --     adds dur:     901896426 nanoseconds of scrolling.
-  --
-  -- gesture_scroll_id: 2917
-  --     starts at: 546027000403
-  --     ends at:   546753574829
-  --     adds dur:     726574426 nanoseconds of scrolling.
-  -- This means we should have scroll_dur = 1628470852
-  SELECT SUM(scroll_dur) FROM (
-    SELECT
-      gesture_scroll_id, max(maybe_gesture_end) - begin_ts AS scroll_dur
-    FROM scroll_jank
-    GROUP BY gesture_scroll_id
-  )
-) AS scroll_dur,
-(
-  -- This can be verified by the following simple query to ensure the end result
-  -- in scroll_jank table is sane. The result should be 139.
-  -- SELECT
-  --   COUNT(*)
-  -- FROM slice
-  -- WHERE
-  --    name = "InputLatency::GestureScrollUpdate" AND
-  --    NOT EXTRACT_ARG(arg_set_id, 'chrome_latency_info.is_coalesced') AND
-  --    (
-  --    EXTRACT_ARG(arg_set_id, 'chrome_latency_info.gesture_scroll_id') = 2708
-  --    OR
-  --    EXTRACT_ARG(arg_set_id, 'chrome_latency_info.gesture_scroll_id') = 2917
-  --    )
-  SELECT COUNT(*) FROM scroll_jank
-) AS non_coalesced_updates,
-(
-  -- This can be verified by the following simple query as above but replace
-  -- COUNT(*) with SUM(dur). The result should be 3974685214.
-  SELECT SUM(dur) FROM scroll_jank
-) AS non_coalesced_dur,
-(
-  -- This was found by running the previous metric before porting on the
-  -- example trace.
-  SELECT COUNT(*) FROM scroll_jank WHERE jank
-) AS non_coalesced_janky_updates,
-(
-  -- This was found by running the previous metric before porting on the
-  -- example trace, and also manually summing them.
-  SELECT SUM(dur) FROM scroll_jank WHERE jank
-) AS non_coalesced_janky_dur,
-(
-  -- This is floor((non_coalesced_janky_dur/non_coalesced_dur) * 100) in SQLite.
-  SELECT
-    CAST((CAST((SELECT SUM(dur) FROM scroll_jank WHERE jank) AS FLOAT)
-      / CAST((SELECT SUM(dur) FROM scroll_jank) AS FLOAT)) * 100 AS INT)
-) AS janky_percentage,
-(
-  SELECT avg_vsync_interval FROM joined_scroll_begin_and_end
-) AS avg_vsync_interval;
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_gpu_check.py b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_gpu_check.py
deleted file mode 100755
index 9defcce..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_gpu_check.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Discarded events that do not get to GPU are invisible for UMA metric and
-# therefore should be excluded in trace-based metric. This tests ensures that's
-# the case.
-
-from os import sys
-
-import synth_common
-
-from synth_common import ms_to_ns
-trace = synth_common.create_trace()
-
-from chrome_scroll_helper import ChromeScrollHelper
-
-helper = ChromeScrollHelper(trace, start_id=1234, start_gesture_id=5678)
-
-helper.begin(from_ms=0, dur_ms=10)
-helper.update(from_ms=15, dur_ms=10)
-# The next update should be recognized as janky
-helper.update(from_ms=30, dur_ms=30)
-helper.end(from_ms=70, dur_ms=10)
-
-helper.begin(from_ms=100, dur_ms=10)
-helper.update(from_ms=115, dur_ms=10)
-# The next update doesn't get to GPU, therefore would not be a part of jank
-# calculation
-helper.update(from_ms=130, dur_ms=30, gets_to_gpu=False)
-helper.end(from_ms=170, dur_ms=10)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_mojo_simple_watcher.out b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_mojo_simple_watcher.out
deleted file mode 100644
index 207e7d2..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_mojo_simple_watcher.out
+++ /dev/null
@@ -1,5 +0,0 @@
-
-"trace_id","jank","dur_overlapping_ns","metric_name"
-34577,0,6000000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.task-subtask"
-34578,1,29000000,"InputLatency.LatencyInfo.Flow.QueuingDelay.Jank.BlockingTasksUs.task-subtask"
-34579,0,29000000,"InputLatency.LatencyInfo.Flow.QueuingDelay.NoJank.BlockingTasksUs.task-foo"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_mojo_simple_watcher.py b/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_mojo_simple_watcher.py
deleted file mode 100755
index 39196947..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_mojo_simple_watcher.py
+++ /dev/null
@@ -1,179 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This is intended to test the handling of simple_watcher style mojo events,
-# which are often missing trace events below them and so are all aggregated
-# together despite them coming into different mojo interfaces.
-
-from os import sys
-
-import synth_common
-
-from synth_common import ms_to_ns
-trace = synth_common.create_trace()
-
-process_track1 = 1234
-
-trace.add_process_track_descriptor(process_track1, pid=0)
-
-process_pid1 = 2345
-
-thread_track1 = 1235
-
-# Main threads have the same ID as the process
-thread_tid1 = process_pid1
-
-seq1 = 9876
-
-thread1_counter = 60
-
-scroll_begin_trace_id = 34576
-trace_id1 = scroll_begin_trace_id + 1
-trace_id2 = trace_id1 + 1
-trace_id3 = trace_id2 + 1
-scroll_end_trace_id = trace_id3 + 1
-
-gesture_scroll_id = 87654
-
-flow_id1 = 45678
-flow_id2 = 45679
-flow_id3 = 45680
-
-trace.add_input_latency_event_slice(
-    "GestureScrollBegin",
-    ts=ms_to_ns(0),
-    dur=ms_to_ns(1),
-    track=scroll_begin_trace_id,
-    trace_id=scroll_begin_trace_id,
-    gesture_scroll_id=gesture_scroll_id)
-
-trace.add_chrome_process_track_descriptor(process_track1, process_pid1)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track1,
-    thread_track1,
-    trusted_packet_sequence_id=seq1,
-    counter_track=thread1_counter,
-    pid=process_pid1,
-    tid=thread_tid1,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-# Scroll update 1 - not janky
-trace.add_input_latency_event_slice(
-    "GestureScrollUpdate",
-    ts=ms_to_ns(0),
-    dur=ms_to_ns(10),
-    track=trace_id1,
-    trace_id=trace_id1,
-    gesture_scroll_id=gesture_scroll_id,
-    is_coalesced=0)
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(0),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id1,
-    flow_ids=[flow_id1])
-
-# The slices below will block this "not janky" scroll update 1.
-trace.add_track_event_slice(
-    "task", ts=ms_to_ns(2), dur=ms_to_ns(6), trusted_sequence_id=seq1)
-
-trace.add_track_event_slice(
-    "subtask", ts=ms_to_ns(3), dur=ms_to_ns(4), trusted_sequence_id=seq1)
-# This ends the blocking slices of "not janky" scroll update 1.
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(11),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id1,
-    terminating_flow_ids=[flow_id1])
-
-# Scroll update 2 - janky
-trace.add_input_latency_event_slice(
-    "GestureScrollUpdate",
-    ts=ms_to_ns(16),
-    dur=ms_to_ns(33),
-    track=trace_id2,
-    trace_id=trace_id2,
-    gesture_scroll_id=gesture_scroll_id,
-    is_coalesced=0)
-
-# This is a special event that adds a track event that stretches the entire
-# trace. This should not impact our metric (our metric should ignore it).
-# See b/184134310 for details of why we are testing this.
-trace.add_track_event_slice_begin(
-    "ThreadController active", ts=ms_to_ns(16), trusted_sequence_id=seq1)
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(16),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id2,
-    flow_ids=[flow_id2])
-
-# The slices below will block this "janky" scroll update 2.
-trace.add_track_event_slice(
-    "task", ts=ms_to_ns(18), dur=ms_to_ns(29), trusted_sequence_id=seq1)
-
-trace.add_track_event_slice(
-    "subtask", ts=ms_to_ns(19), dur=ms_to_ns(27), trusted_sequence_id=seq1)
-# This ends the blocking slices of "janky" scroll update 2.
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(50),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id2,
-    terminating_flow_ids=[flow_id2])
-
-# Scroll update 3 - janky
-trace.add_input_latency_event_slice(
-    "GestureScrollUpdate",
-    ts=ms_to_ns(55),
-    dur=ms_to_ns(33),
-    track=trace_id3,
-    trace_id=trace_id3,
-    gesture_scroll_id=gesture_scroll_id,
-    is_coalesced=0)
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(55),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id3,
-    flow_ids=[flow_id3])
-
-# The slices below will block this "janky" scroll update 3.
-trace.add_track_event_slice(
-    "task", ts=ms_to_ns(57), dur=ms_to_ns(29), trusted_sequence_id=seq1)
-
-packet = trace.add_track_event_slice(
-    "subtask", ts=ms_to_ns(58), dur=ms_to_ns(27), trusted_sequence_id=seq1)
-
-packet.track_event.chrome_mojo_event_info.watcher_notify_interface_tag = "foo"
-# This ends the blocking slices of "janky" scroll update 3.
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(89),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id3,
-    terminating_flow_ids=[flow_id3])
-
-trace.add_input_latency_event_slice(
-    "GestureScrollEnd",
-    ts=ms_to_ns(90),
-    dur=ms_to_ns(2),
-    track=scroll_end_trace_id,
-    trace_id=scroll_end_trace_id,
-    gesture_scroll_id=gesture_scroll_id)
-
-# This ends the "ThreadController active" event.
-trace.add_track_event_slice_end(ts=ms_to_ns(94), trusted_sequence_id=seq1)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/tests.py b/base/tracing/test/trace_processor/diff_tests/chrome/tests.py
index 784af81..ddc088e5 100755
--- a/base/tracing/test/trace_processor/diff_tests/chrome/tests.py
+++ b/base/tracing/test/trace_processor/diff_tests/chrome/tests.py
@@ -9,232 +9,7 @@
 from python.generators.diff_tests.testing import TestSuite
 
 
-class Chrome(TestSuite):
-  # Tests related to Chrome's use of Perfetto. Chrome histogram hashes
-  def test_chrome_histogram_hashes(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 0
-          incremental_state_cleared: true
-          track_event {
-            categories: "cat1"
-            type: 3
-            name_iid: 1
-            chrome_histogram_sample {
-              name_hash: 10
-              sample: 100
-            }
-          }
-        }
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 0
-          incremental_state_cleared: true
-          track_event {
-            categories: "cat2"
-            type: 3
-            name_iid: 2
-            chrome_histogram_sample {
-              name_hash: 20
-            }
-          }
-        }
-        """),
-        query=Metric('chrome_histogram_hashes'),
-        out=TextProto(r"""
-        [perfetto.protos.chrome_histogram_hashes]: {
-          hash: 10
-          hash: 20
-        }
-        """))
-
-  # Chrome user events
-  def test_chrome_user_event_hashes(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 0
-          incremental_state_cleared: true
-          track_event {
-            categories: "cat1"
-            type: 3
-            name_iid: 1
-            chrome_user_event {
-              action_hash: 10
-            }
-          }
-        }
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 0
-          incremental_state_cleared: true
-          track_event {
-            categories: "cat2"
-            type: 3
-            name_iid: 2
-            chrome_user_event {
-              action_hash: 20
-            }
-          }
-        }
-        """),
-        query=Metric('chrome_user_event_hashes'),
-        out=TextProto(r"""
-        [perfetto.protos.chrome_user_event_hashes]: {
-          action_hash: 10
-          action_hash: 20
-        }
-        """))
-
-  # Chrome performance mark
-  def test_chrome_performance_mark_hashes(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 0
-          incremental_state_cleared: true
-          track_event {
-            categories: "cat1"
-            type: 3
-            name: "name1"
-            [perfetto.protos.ChromeTrackEvent.chrome_hashed_performance_mark] {
-              site_hash: 10
-              mark_hash: 100
-            }
-          }
-        }
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 0
-          incremental_state_cleared: true
-          track_event {
-            categories: "cat2"
-            type: 3
-            name: "name2"
-            [perfetto.protos.ChromeTrackEvent.chrome_hashed_performance_mark] {
-              site_hash: 20
-              mark_hash: 200
-            }
-          }
-        }
-        """),
-        query=Metric('chrome_performance_mark_hashes'),
-        out=TextProto(r"""
-        [perfetto.protos.chrome_performance_mark_hashes]: {
-          site_hash: 10
-          site_hash: 20
-          mark_hash: 100
-          mark_hash: 200
-        }
-        """))
-
-  # Chrome reliable range
-  def test_chrome_reliable_range(self):
-    return DiffTestBlueprint(
-        trace=Path('chrome_reliable_range.textproto'),
-        query=Path('chrome_reliable_range_test.sql'),
-        out=Csv("""
-        "start","reason","debug_limiting_upid","debug_limiting_utid"
-        12,"First slice for utid=2","[NULL]",2
-        """))
-
-  def test_chrome_reliable_range_cropping(self):
-    return DiffTestBlueprint(
-        trace=Path('chrome_reliable_range_cropping.textproto'),
-        query=Path('chrome_reliable_range_test.sql'),
-        out=Csv("""
-        "start","reason","debug_limiting_upid","debug_limiting_utid"
-        10000,"Range of interest packet","[NULL]",2
-        """))
-
-  def test_chrome_reliable_range_missing_processes(self):
-    return DiffTestBlueprint(
-        trace=Path('chrome_reliable_range_missing_processes.textproto'),
-        query=Path('chrome_reliable_range_test.sql'),
-        out=Csv("""
-        "start","reason","debug_limiting_upid","debug_limiting_utid"
-        1011,"Missing process data for upid=2",2,1
-        """))
-
-  def test_chrome_reliable_range_missing_browser_main(self):
-    return DiffTestBlueprint(
-        trace=Path('chrome_reliable_range_missing_browser_main.textproto'),
-        query=Path('chrome_reliable_range_test.sql'),
-        out=Csv("""
-        "start","reason","debug_limiting_upid","debug_limiting_utid"
-        1011,"Missing main thread for upid=1",1,1
-        """))
-
-  def test_chrome_reliable_range_missing_gpu_main(self):
-    return DiffTestBlueprint(
-        trace=Path('chrome_reliable_range_missing_gpu_main.textproto'),
-        query=Path('chrome_reliable_range_test.sql'),
-        out=Csv("""
-        "start","reason","debug_limiting_upid","debug_limiting_utid"
-        1011,"Missing main thread for upid=1",1,1
-        """))
-
-  def test_chrome_reliable_range_missing_renderer_main(self):
-    return DiffTestBlueprint(
-        trace=Path('chrome_reliable_range_missing_renderer_main.textproto'),
-        query=Path('chrome_reliable_range_test.sql'),
-        out=Csv("""
-        "start","reason","debug_limiting_upid","debug_limiting_utid"
-        1011,"Missing main thread for upid=1",1,1
-        """))
-
-  def test_chrome_reliable_range_non_chrome_process(self):
-    return DiffTestBlueprint(
-        # We need a trace with a large number of non-chrome slices, so that the
-        # reliable range is affected by their filtering.
-        trace=DataPath('example_android_trace_30s.pb'),
-        query=Path('chrome_reliable_range_test.sql'),
-        out=Csv("""
-        "start","reason","debug_limiting_upid","debug_limiting_utid"
-        0,"[NULL]","[NULL]","[NULL]"
-        """))
-
-  # Chrome slices
-  def test_chrome_slice_names(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 1000
-          track_event {
-            categories: "cat"
-            name: "Looper.Dispatch: class1"
-            type: 3
-          }
-        }
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 2000
-          track_event {
-            categories: "cat"
-            name: "name2"
-            type: 3
-          }
-        }
-        packet {
-          chrome_metadata {
-            chrome_version_code: 123
-          }
-        }
-        """),
-        query=Metric('chrome_slice_names'),
-        out=TextProto(r"""
-        [perfetto.protos.chrome_slice_names]: {
-          chrome_version_code: 123
-          slice_name: "Looper.Dispatch: class1"
-          slice_name: "name2"
-        }
-        """))
-
+class ChromeStdlib(TestSuite):
   # Chrome tasks.
   def test_chrome_tasks(self):
     return DiffTestBlueprint(
@@ -270,201 +45,6 @@
             'top_level_java_choreographer_slices_top_level_java_chrome_tasks_test.out'
         ))
 
-  # Chrome stack samples.
-  def test_chrome_stack_samples_for_task(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_stack_traces_symbolized_trace.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/chrome_stack_samples_for_task.sql',
-            'target_duration_ms', '0.000001',
-            'thread_name', '"CrBrowserMain"',
-            'task_name', '"sendTouchEvent"');
-
-        SELECT
-          sample.description,
-          sample.ts,
-          sample.depth
-        FROM chrome_stack_samples_for_task sample
-        JOIN (
-            SELECT
-              ts,
-              dur
-            FROM slice
-            WHERE ts = 696373965001470
-        ) test_slice
-        ON sample.ts >= test_slice.ts
-          AND sample.ts <= test_slice.ts + test_slice.dur
-        ORDER BY sample.ts, sample.depth;
-        """,
-        out=Path('chrome_stack_samples_for_task_test.out'))
-
-  # Log messages.
-  def test_chrome_log_message(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          timestamp: 0
-          incremental_state_cleared: true
-          trusted_packet_sequence_id: 1
-          track_descriptor {
-            uuid: 12345
-            thread {
-              pid: 123
-              tid: 345
-            }
-            parent_uuid: 0
-            chrome_thread {
-              thread_type: THREAD_POOL_FG_WORKER
-            }
-          }
-        }
-
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 10
-          track_event {
-            track_uuid: 12345
-            categories: "cat1"
-            type: TYPE_INSTANT
-            name: "slice1"
-            log_message {
-                body_iid: 1
-                source_location_iid: 3
-            }
-          }
-          interned_data {
-            log_message_body {
-                iid: 1
-                body: "log message"
-            }
-            source_locations {
-                iid: 3
-                function_name: "func"
-                file_name: "foo.cc"
-                line_number: 123
-            }
-          }
-        }
-        """),
-        query="""
-        SELECT utid, tag, msg, prio FROM android_logs;
-        """,
-        # If the log_message_body doesn't have any priority, a default 4 (i.e.
-        # INFO) is assumed (otherwise the UI will not show the message).
-        out=Csv("""
-        "utid","tag","msg","prio"
-        1,"foo.cc:123","log message",4
-        """))
-
-  def test_chrome_log_message_priority(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          timestamp: 0
-          incremental_state_cleared: true
-          trusted_packet_sequence_id: 1
-          track_descriptor {
-            uuid: 12345
-            thread {
-              pid: 123
-              tid: 345
-            }
-            parent_uuid: 0
-            chrome_thread {
-              thread_type: THREAD_POOL_FG_WORKER
-            }
-          }
-        }
-
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 10
-          track_event {
-            track_uuid: 12345
-            categories: "cat1"
-            type: TYPE_INSTANT
-            name: "slice1"
-            log_message {
-                body_iid: 1
-                source_location_iid: 3
-                prio: PRIO_WARN
-            }
-          }
-          interned_data {
-            log_message_body {
-                iid: 1
-                body: "log message"
-            }
-            source_locations {
-                iid: 3
-                function_name: "func"
-                file_name: "foo.cc"
-                line_number: 123
-            }
-          }
-        }
-        """),
-        query="""
-        SELECT utid, tag, msg, prio FROM android_logs;
-        """,
-        out=Csv("""
-        "utid","tag","msg","prio"
-        1,"foo.cc:123","log message",5
-        """))
-
-  def test_chrome_log_message_args(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          timestamp: 0
-          incremental_state_cleared: true
-          trusted_packet_sequence_id: 1
-          track_descriptor {
-            uuid: 12345
-            thread {
-              pid: 123
-              tid: 345
-            }
-            parent_uuid: 0
-            chrome_thread {
-              thread_type: THREAD_POOL_FG_WORKER
-            }
-          }
-        }
-
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 10
-          track_event {
-            track_uuid: 12345
-            categories: "cat1"
-            type: TYPE_INSTANT
-            name: "slice1"
-            log_message {
-                body_iid: 1
-                source_location_iid: 3
-            }
-          }
-          interned_data {
-            log_message_body {
-                iid: 1
-                body: "log message"
-            }
-            source_locations {
-                iid: 3
-                function_name: "func"
-                file_name: "foo.cc"
-                line_number: 123
-            }
-          }
-        }
-        """),
-        query=Path('chrome_log_message_args_test.sql'),
-        out=Csv("""
-        "log_message","function_name","file_name","line_number"
-        "log message","func","foo.cc",123
-        """))
-
   # Chrome custom navigation event names
   def test_chrome_custom_navigation_tasks(self):
     return DiffTestBlueprint(
@@ -529,36 +109,44 @@
         "Net.HttpResponseCode",541
         """))
 
-  # Trace proto content
-  def test_proto_content(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query=Path('proto_content_test.sql'),
-        out=Path('proto_content.out'))
-
   def test_speedometer(self):
     return DiffTestBlueprint(
         trace=DataPath('speedometer.perfetto_trace.gz'),
-        query=Path('chrome_speedometer_test.sql'),
+        query="""
+        INCLUDE PERFETTO MODULE chrome.speedometer;
+
+        SELECT
+          iteration,
+          ts,
+          dur,
+          total,
+          format('%.1f', mean) AS mean,
+          format('%.1f', geomean) AS geomean,
+          format('%.1f', score) AS score,
+          num_measurements
+        FROM
+          chrome_speedometer_iteration,
+          (
+            SELECT iteration, COUNT(*) AS num_measurements
+            FROM chrome_speedometer_measure
+            GROUP BY iteration
+          )
+        USING (iteration)
+        ORDER BY iteration;
+        """,
         out=Path('chrome_speedometer.out'))
 
-  # TODO(mayzner): Uncomment when it works
-  # def test_proto_content_path(self):
-  #   return DiffTestBlueprint(
-  #       trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-  #       query=Path('proto_content_path_test.sql'),
-  #       out=Csv("""
-  #       "total_size","field_type","field_name","parent_id","event_category",
-  #                                                          "event_name"
-  #       137426,"TracePacket","[NULL]","[NULL]","[NULL]","[NULL]"
-  #       59475,"TrackEvent","#track_event",415,"[NULL]","[NULL]"
-  #       37903,"TrackEvent","#track_event",17,"[NULL]","[NULL]"
-  #       35904,"int32","#trusted_uid",17,"[NULL]","[NULL]"
-  #       35705,"TracePacket","[NULL]","[NULL]","input,benchmark",
-  #                                             "LatencyInfo.Flow"
-  #       29403,"TracePacket","[NULL]","[NULL]","cc,input","[NULL]"
-  #       24703,"ChromeLatencyInfo","#chrome_latency_info",18,"[NULL]","[NULL]"
-  #       22620,"uint64","#time_us",26,"[NULL]","[NULL]"
-  #       18711,"TrackEvent","#track_event",1467,"[NULL]","[NULL]"
-  #       15606,"uint64","#timestamp",17,"[NULL]","[NULL]"
-  #       """))
+  # CPU power ups
+  def test_cpu_powerups(self):
+    return DiffTestBlueprint(
+        trace=DataPath('cpu_powerups_1.pb'),
+        query="""
+        INCLUDE PERFETTO MODULE chrome.cpu_powerups;
+        SELECT * FROM chrome_cpu_power_first_toplevel_slice_after_powerup;
+        """,
+        out=Csv("""
+        "slice_id","previous_power_state"
+        424,2
+        703,2
+        708,2
+        """))
\ No newline at end of file
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/tests_args.py b/base/tracing/test/trace_processor/diff_tests/chrome/tests_args.py
deleted file mode 100755
index 29b268ff..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/tests_args.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from python.generators.diff_tests.testing import Path, DataPath, Metric
-from python.generators.diff_tests.testing import Csv, Json, TextProto
-from python.generators.diff_tests.testing import DiffTestBlueprint
-from python.generators.diff_tests.testing import TestSuite
-
-
-class ChromeArgs(TestSuite):
-  # Unsymbolized args.
-  def test_unsymbolized_args(self):
-    return DiffTestBlueprint(
-        trace=Path('unsymbolized_args.textproto'),
-        query=Metric('chrome_unsymbolized_args'),
-        out=TextProto(r"""
-        [perfetto.protos.chrome_unsymbolized_args]: {
-          args {
-             module: "/liblib.so"
-             build_id: "6275696c642d6964"
-             address: 123
-             google_lookup_id: "6275696c642d6964"
-           }
-           args {
-             module: "/libmonochrome_64.so"
-             build_id: "7f0715c286f8b16c10e4ad349cda3b9b56c7a773"
-             address: 234
-             google_lookup_id: "c215077ff8866cb110e4ad349cda3b9b0"
-           }
-        }
-        """))
-
-  def test_async_trace_1_count_slices(self):
-    return DiffTestBlueprint(
-        trace=DataPath('async-trace-1.json'),
-        query="""
-        SELECT COUNT(1) FROM slice;
-        """,
-        out=Csv("""
-        "COUNT(1)"
-        16
-        """))
-
-  def test_async_trace_2_count_slices(self):
-    return DiffTestBlueprint(
-        trace=DataPath('async-trace-2.json'),
-        query="""
-        SELECT COUNT(1) FROM slice;
-        """,
-        out=Csv("""
-        "COUNT(1)"
-        35
-        """))
-
-  # Chrome args class names
-  def test_chrome_args_class_names(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          timestamp: 0
-          incremental_state_cleared: true
-          trusted_packet_sequence_id: 1
-          track_descriptor {
-            uuid: 12345
-            thread {
-              pid: 123
-              tid: 345
-            }
-            parent_uuid: 0
-            chrome_thread {
-              thread_type: THREAD_POOL_FG_WORKER
-            }
-          }
-        }
-
-        packet {
-          trusted_packet_sequence_id: 1
-          timestamp: 0
-          incremental_state_cleared: true
-          track_event {
-            track_uuid: 12345
-            categories: "cat1"
-            type: 3
-            name: "name1"
-            [perfetto.protos.ChromeTrackEvent.android_view_dump] {
-              activity {
-                name: "A"
-                view {
-                  class_name: "abc"
-                },
-                view {
-                  class_name: "def"
-                },
-                view {
-                  class_name: "ghi"
-                }
-              }
-              activity {
-                name: "B"
-                view {
-                  class_name: "jkl"
-                }
-              }
-            }
-          }
-        }
-        """),
-        query=Metric('chrome_args_class_names'),
-        out=TextProto(r"""
-
-        [perfetto.protos.chrome_args_class_names] {
-          class_names_per_version {
-            class_name: "abc"
-            class_name: "def"
-            class_name: "ghi"
-            class_name: "jkl"
-          }
-        }
-        """))
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/tests_chrome_interactions.py b/base/tracing/test/trace_processor/diff_tests/chrome/tests_chrome_interactions.py
new file mode 100755
index 0000000..d7e7f31
--- /dev/null
+++ b/base/tracing/test/trace_processor/diff_tests/chrome/tests_chrome_interactions.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from python.generators.diff_tests.testing import DataPath
+from python.generators.diff_tests.testing import Csv
+from python.generators.diff_tests.testing import DiffTestBlueprint
+from python.generators.diff_tests.testing import TestSuite
+
+
+class ChromeInteractions(TestSuite):
+  def test_chrome_fcp_lcp_navigations(self):
+    return DiffTestBlueprint(
+        trace=DataPath('chrome_fcp_lcp_navigations.pftrace'),
+        query="""
+        INCLUDE PERFETTO MODULE chrome.page_loads;
+
+        SELECT
+          navigation_id,
+          navigation_start_ts,
+          fcp,
+          fcp_ts,
+          lcp,
+          lcp_ts,
+          browser_upid
+        FROM chrome_page_loads
+        ORDER by navigation_start_ts;
+        """,
+        out=Csv("""
+        "navigation_id","navigation_start_ts","fcp","fcp_ts","lcp","lcp_ts","browser_upid"
+        6,687425601436243,950000000,687426551436243,950000000,687426551436243,1
+        7,687427799068243,888000000,687428687068243,888000000,687428687068243,1
+        8,687429970749243,1031000000,687431001749243,1132000000,687431102749243,1
+        9,687432344113243,539000000,687432883113243,539000000,687432883113243,1
+        10,687434796215243,475000000,687435271215243,475000000,687435271215243,1
+        11,687435970742243,763000000,687436733742243,852000000,687436822742243,1
+        13,687438343638243,1005000000,687439348638243,1005000000,687439348638243,1
+        14,687440258111243,900000000,687441158111243,"[NULL]",0,1
+        """))
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/tests_memory_snapshots.py b/base/tracing/test/trace_processor/diff_tests/chrome/tests_memory_snapshots.py
deleted file mode 100755
index 8337a11e..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/tests_memory_snapshots.py
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from python.generators.diff_tests.testing import Path, DataPath, Metric
-from python.generators.diff_tests.testing import Csv, Json, TextProto
-from python.generators.diff_tests.testing import DiffTestBlueprint
-from python.generators.diff_tests.testing import TestSuite
-
-
-class ChromeMemorySnapshots(TestSuite):
-
-  def test_memory_snapshot_general_validation(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_memory_snapshot.pftrace'),
-        query="""
-        SELECT
-          (
-            SELECT COUNT(*) FROM memory_snapshot
-          ) AS total_snapshots,
-          (
-            SELECT COUNT(*) FROM process
-          ) AS total_processes,
-          (
-            SELECT COUNT(*) FROM process_memory_snapshot
-          ) AS total_process_snapshots,
-          (
-            SELECT COUNT(*) FROM memory_snapshot_node
-          ) AS total_nodes,
-          (
-            SELECT COUNT(*) FROM memory_snapshot_edge
-          ) AS total_edges,
-          (
-            SELECT COUNT(DISTINCT args.id)
-            FROM args
-            JOIN memory_snapshot_node
-              ON args.arg_set_id = memory_snapshot_node.arg_set_id
-          ) AS total_node_args,
-          (
-            SELECT COUNT(*) FROM profiler_smaps
-            JOIN memory_snapshot ON timestamp = ts
-          ) AS total_smaps;
-        """,
-        out=Path('memory_snapshot_general_validation.out'))
-
-  def test_memory_snapshot_os_dump_events(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_memory_snapshot.pftrace'),
-        query=Path('memory_snapshot_os_dump_events_test.sql'),
-        out=Path('memory_snapshot_os_dump_events.out'))
-
-  def test_memory_snapshot_chrome_dump_events(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_memory_snapshot.pftrace'),
-        query="""
-        SELECT
-          pms.id AS process_snapshot_id,
-          upid,
-          snapshot_id,
-          timestamp,
-          detail_level
-        FROM memory_snapshot ms
-        LEFT JOIN process_memory_snapshot pms
-          ON ms.id = pms.snapshot_id;
-        """,
-        out=Path('memory_snapshot_chrome_dump_events.out'))
-
-  def test_memory_snapshot_nodes(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_memory_snapshot.pftrace'),
-        query="""
-        SELECT
-          id,
-          process_snapshot_id,
-          parent_node_id,
-          path,
-          size,
-          effective_size
-        FROM memory_snapshot_node
-        LIMIT 20;
-        """,
-        out=Path('memory_snapshot_nodes.out'))
-
-  def test_memory_snapshot_edges(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_memory_snapshot.pftrace'),
-        query="""
-        SELECT
-          id,
-          source_node_id,
-          target_node_id,
-          importance
-        FROM memory_snapshot_edge
-        LIMIT 20;
-        """,
-        out=Path('memory_snapshot_edges.out'))
-
-  def test_memory_snapshot_node_args(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_memory_snapshot.pftrace'),
-        query="""
-        SELECT
-          node.id AS node_id,
-          key,
-          value_type,
-          int_value,
-          string_value
-        FROM memory_snapshot_node node
-        JOIN args ON node.arg_set_id = args.arg_set_id
-        LIMIT 20;
-        """,
-        out=Path('memory_snapshot_node_args.out'))
-
-  def test_memory_snapshot_smaps(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_memory_snapshot.pftrace'),
-        query="""
-        SELECT
-          process.upid,
-          process.name,
-          smap.ts,
-          path,
-          size_kb,
-          private_dirty_kb,
-          swap_kb,
-          file_name,
-          start_address,
-          module_timestamp,
-          module_debugid,
-          module_debug_path,
-          protection_flags,
-          private_clean_resident_kb,
-          shared_dirty_resident_kb,
-          shared_clean_resident_kb,
-          locked_kb,
-          proportional_resident_kb
-        FROM process
-        JOIN profiler_smaps smap ON process.upid = smap.upid
-        JOIN memory_snapshot ms ON ms.timestamp = smap.ts
-        LIMIT 20;
-        """,
-        out=Path('memory_snapshot_smaps.out'))
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/tests_processes.py b/base/tracing/test/trace_processor/diff_tests/chrome/tests_processes.py
deleted file mode 100755
index 2bbf29fc..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/tests_processes.py
+++ /dev/null
@@ -1,373 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from python.generators.diff_tests.testing import Path, DataPath, Metric
-from python.generators.diff_tests.testing import Csv, Json, TextProto
-from python.generators.diff_tests.testing import DiffTestBlueprint
-from python.generators.diff_tests.testing import TestSuite
-
-
-class ChromeProcesses(TestSuite):
-
-  def test_chrome_processes(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/chrome_processes.sql');
-        SELECT pid, name, process_type FROM chrome_process;
-        """,
-        out=Csv("""
-        "pid","name","process_type"
-        18250,"Renderer","Renderer"
-        17547,"Browser","Browser"
-        18277,"GPU Process","Gpu"
-        17578,"Browser","Browser"
-        """))
-
-  def test_chrome_processes_android_systrace(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_android_systrace.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/chrome_processes.sql');
-        SELECT pid, name, process_type FROM chrome_process;
-        """,
-        out=Path('chrome_processes_android_systrace.out'))
-
-  def test_chrome_threads(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/chrome_processes.sql');
-        SELECT tid, name, is_main_thread, canonical_name
-        FROM chrome_thread
-        ORDER BY tid, name;
-        """,
-        out=Path('chrome_threads.out'))
-
-  def test_chrome_threads_android_systrace(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_android_systrace.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/chrome_processes.sql');
-        SELECT tid, name, is_main_thread, canonical_name
-        FROM chrome_thread
-        ORDER BY tid, name;
-        """,
-        out=Path('chrome_threads_android_systrace.out'))
-
-  def test_chrome_processes_type(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT pid, name, string_value AS chrome_process_type
-        FROM
-          process
-        JOIN
-          (SELECT * FROM args WHERE key = "chrome.process_type")
-          chrome_process_args
-          ON
-            process.arg_set_id = chrome_process_args.arg_set_id
-        ORDER BY pid;
-        """,
-        out=Csv("""
-        "pid","name","chrome_process_type"
-        17547,"Browser","Browser"
-        17578,"Browser","Browser"
-        18250,"Renderer","Renderer"
-        18277,"GPU Process","Gpu"
-        """))
-
-  def test_chrome_processes_type_android_systrace(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_android_systrace.pftrace'),
-        query="""
-        SELECT pid, name, string_value AS chrome_process_type
-        FROM
-          process
-        JOIN
-          (SELECT * FROM args WHERE key = "chrome.process_type")
-          chrome_process_args
-          ON
-            process.arg_set_id = chrome_process_args.arg_set_id
-        ORDER BY pid;
-        """,
-        out=Path('chrome_processes_type_android_systrace.out'))
-
-  def test_track_with_chrome_process(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          trusted_packet_sequence_id: 1
-          incremental_state_cleared: true
-          timestamp: 0
-          track_descriptor {
-            uuid: 10
-            process {
-              pid: 5
-              process_name: "p5"
-            }
-            # Empty Chrome process. This is similar to a process descriptor
-            # emitted by Chrome for a process with an unknown Chrome
-            # process_type. This process should still receive a
-            # "chrome_process_type" arg in the args table, but with a NULL
-            # value.
-            chrome_process {}
-          }
-        }
-        """),
-        query="""
-        SELECT pid, name, string_value AS chrome_process_type
-        FROM
-          process
-        JOIN
-          (SELECT * FROM args WHERE key = "chrome.process_type")
-          chrome_process_args
-          ON
-            process.arg_set_id = chrome_process_args.arg_set_id
-        ORDER BY pid;
-        """,
-        out=Csv("""
-        "pid","name","chrome_process_type"
-        5,"p5","[NULL]"
-        """))
-
-  # Missing processes.
-  def test_chrome_missing_processes_default_trace(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT pid, reliable_from
-        FROM
-          experimental_missing_chrome_processes
-        JOIN
-          process
-          USING(upid)
-        ORDER BY upid;
-        """,
-        out=Csv("""
-        "pid","reliable_from"
-        """))
-
-  def test_chrome_missing_processes(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          timestamp: 1
-          incremental_state_cleared: true
-          trusted_packet_sequence_id: 1
-          track_event {
-            type: TYPE_INSTANT
-            name: "ActiveProcesses"
-            chrome_active_processes {
-              pid: 10
-              pid: 100
-              pid: 1000
-            }
-          }
-        }
-        packet {
-          timestamp: 1
-          trusted_packet_sequence_id: 2
-          track_descriptor {
-            uuid: 1
-            process {
-              pid: 10
-            }
-            parent_uuid: 0
-          }
-        }
-        packet {
-          timestamp: 1000000000
-          trusted_packet_sequence_id: 3
-          track_descriptor {
-            uuid: 2
-            process {
-              pid: 100
-            }
-            parent_uuid: 0
-          }
-        }
-        """),
-        query="""
-        SELECT pid, reliable_from
-        FROM
-          experimental_missing_chrome_processes
-        JOIN
-          process
-          USING(upid)
-        ORDER BY upid;
-        """,
-        out=Csv("""
-        "pid","reliable_from"
-        100,1000000000
-        1000,"[NULL]"
-        """))
-
-  def test_chrome_missing_processes_args(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          timestamp: 1
-          incremental_state_cleared: true
-          trusted_packet_sequence_id: 1
-          track_event {
-            type: TYPE_INSTANT
-            name: "ActiveProcesses"
-            chrome_active_processes {
-              pid: 10
-              pid: 100
-              pid: 1000
-            }
-          }
-        }
-        packet {
-          timestamp: 1
-          trusted_packet_sequence_id: 2
-          track_descriptor {
-            uuid: 1
-            process {
-              pid: 10
-            }
-            parent_uuid: 0
-          }
-        }
-        packet {
-          timestamp: 1000000000
-          trusted_packet_sequence_id: 3
-          track_descriptor {
-            uuid: 2
-            process {
-              pid: 100
-            }
-            parent_uuid: 0
-          }
-        }
-        """),
-        query="""
-        SELECT slice.name, key, int_value
-        FROM
-          slice
-        JOIN
-          args
-          USING(arg_set_id)
-        ORDER BY arg_set_id, key;
-        """,
-        out=Csv("""
-        "name","key","int_value"
-        "ActiveProcesses","chrome_active_processes.pid[0]",10
-        "ActiveProcesses","chrome_active_processes.pid[1]",100
-        "ActiveProcesses","chrome_active_processes.pid[2]",1000
-        """))
-
-  def test_chrome_missing_processes_2(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          timestamp: 1
-          incremental_state_cleared: true
-          trusted_packet_sequence_id: 1
-          track_event {
-            type: TYPE_INSTANT
-            name: "ActiveProcesses"
-            [perfetto.protos.ChromeTrackEvent.active_processes]: {
-              pid: 10
-              pid: 100
-              pid: 1000
-            }
-          }
-        }
-        packet {
-          timestamp: 1
-          trusted_packet_sequence_id: 2
-          track_descriptor {
-            uuid: 1
-            process {
-              pid: 10
-            }
-            parent_uuid: 0
-          }
-        }
-        packet {
-          timestamp: 1000000000
-          trusted_packet_sequence_id: 3
-          track_descriptor {
-            uuid: 2
-            process {
-              pid: 100
-            }
-            parent_uuid: 0
-          }
-        }
-        """),
-        query="""
-        SELECT pid, reliable_from
-        FROM
-          experimental_missing_chrome_processes
-        JOIN
-          process
-          USING(upid)
-        ORDER BY upid;
-        """,
-        out=Csv("""
-        "pid","reliable_from"
-        100,1000000000
-        1000,"[NULL]"
-        """))
-
-  def test_chrome_missing_processes_extension_args(self):
-    return DiffTestBlueprint(
-        trace=TextProto(r"""
-        packet {
-          timestamp: 1
-          incremental_state_cleared: true
-          trusted_packet_sequence_id: 1
-          track_event {
-            type: TYPE_INSTANT
-            name: "ActiveProcesses"
-            [perfetto.protos.ChromeTrackEvent.active_processes]: {
-              pid: 10
-              pid: 100
-              pid: 1000
-            }
-          }
-        }
-        packet {
-          timestamp: 1
-          trusted_packet_sequence_id: 2
-          track_descriptor {
-            uuid: 1
-            process {
-              pid: 10
-            }
-            parent_uuid: 0
-          }
-        }
-        packet {
-          timestamp: 1000000000
-          trusted_packet_sequence_id: 3
-          track_descriptor {
-            uuid: 2
-            process {
-              pid: 100
-            }
-            parent_uuid: 0
-          }
-        }
-        """),
-        query="""
-        SELECT slice.name, key, int_value
-        FROM
-          slice
-        JOIN
-          args
-          USING(arg_set_id)
-        ORDER BY arg_set_id, key;
-        """,
-        out=Csv("""
-        "name","key","int_value"
-        "ActiveProcesses","active_processes.pid[0]",10
-        "ActiveProcesses","active_processes.pid[1]",100
-        "ActiveProcesses","active_processes.pid[2]",1000
-        """))
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/tests_rail_modes.py b/base/tracing/test/trace_processor/diff_tests/chrome/tests_rail_modes.py
deleted file mode 100755
index 672fa6e..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/tests_rail_modes.py
+++ /dev/null
@@ -1,151 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from python.generators.diff_tests.testing import Path, DataPath, Metric
-from python.generators.diff_tests.testing import Csv, Json, TextProto
-from python.generators.diff_tests.testing import DiffTestBlueprint
-from python.generators.diff_tests.testing import TestSuite
-
-
-class ChromeRailModes(TestSuite):
-
-  def test_combined_rail_modes(self):
-    return DiffTestBlueprint(
-        trace=Path('combined_rail_modes.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/rail_modes.sql');
-        SELECT * FROM combined_overall_rail_slices;
-        """,
-        out=Csv("""
-        "id","ts","dur","rail_mode"
-        1,0,10000,"response"
-        2,10000,25000,"animation"
-        3,35000,10000,"background"
-        """))
-
-  def test_cpu_time_by_combined_rail_mode(self):
-    return DiffTestBlueprint(
-        trace=Path('cpu_time_by_combined_rail_mode.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/cpu_time_by_rail_mode.sql');
-        SELECT * FROM cpu_time_by_rail_mode;
-        """,
-        out=Csv("""
-        "id","ts","dur","rail_mode","cpu_dur"
-        1,0,10000,"response",26000
-        2,10000,20000,"animation",20000
-        3,30000,5000,"background",8000
-        4,35000,10000,"animation",21000
-        5,45000,10000,"background",1000
-        """))
-
-  def test_actual_power_by_combined_rail_mode(self):
-    return DiffTestBlueprint(
-        trace=Path('actual_power_by_combined_rail_mode.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/actual_power_by_rail_mode.sql');
-        SELECT * FROM real_power_by_rail_mode;
-        """,
-        out=Csv("""
-        "id","ts","dur","rail_mode","subsystem","joules","drain_w"
-        1,0,10000000,"response","cellular",0.000000,0.000000
-        1,0,10000000,"response","cpu_little",0.000140,0.014000
-        2,10000000,20000000,"animation","cellular",0.000350,0.017500
-        2,10000000,20000000,"animation","cpu_little",0.000140,0.007000
-        3,30000000,5000000,"background","cellular",0.000018,0.003500
-        3,30000000,5000000,"background","cpu_little",0.000007,0.001400
-        4,35000000,10000000,"animation","cellular",0.000021,0.002100
-        4,35000000,10000000,"animation","cpu_little",0.000070,0.007000
-        5,45000000,10000000,"background","cellular",0.000003,0.000350
-        5,45000000,10000000,"background","cpu_little",0.000070,0.007000
-        """))
-
-  def test_estimated_power_by_combined_rail_mode(self):
-    return DiffTestBlueprint(
-        trace=Path('estimated_power_by_combined_rail_mode.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/estimated_power_by_rail_mode.sql');
-        SELECT * FROM power_by_rail_mode;
-        """,
-        out=Csv("""
-        "id","ts","dur","rail_mode","mas","ma"
-        1,0,10000000,"response",0.554275,55.427500
-        2,10000000,20000000,"animation",0.284850,14.242500
-        3,30000000,5000000,"background",0.076233,15.246667
-        4,35000000,10000000,"animation",0.536850,53.685000
-        5,45000000,10000000,"background",0.071580,7.158000
-        """))
-
-  def test_modified_rail_modes(self):
-    return DiffTestBlueprint(
-        trace=Path('modified_rail_modes.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/rail_modes.sql');
-        SELECT * FROM modified_rail_slices;
-        """,
-        out=Csv("""
-        "id","ts","dur","mode"
-        2,0,1000000000,"response"
-        3,1000000000,1950000000,"foreground_idle"
-        4,2950000000,333333324,"animation"
-        5,3283333324,216666676,"foreground_idle"
-        6,3500000000,1000000000,"background"
-        """))
-
-  def test_modified_rail_modes_no_vsyncs(self):
-    return DiffTestBlueprint(
-        trace=Path('modified_rail_modes_no_vsyncs.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/rail_modes.sql');
-        SELECT * FROM modified_rail_slices;
-        """,
-        out=Csv("""
-        "id","ts","dur","mode"
-        2,0,1000000000,"response"
-        3,1000000000,2500000000,"foreground_idle"
-        4,3500000000,1000000000,"background"
-        """))
-
-  def test_modified_rail_modes_with_input(self):
-    return DiffTestBlueprint(
-        trace=Path('modified_rail_modes_with_input.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/rail_modes.sql');
-        SELECT * FROM modified_rail_slices;
-        """,
-        out=Csv("""
-        "id","ts","dur","mode"
-        2,0,1000000000,"response"
-        3,1000000000,1950000000,"foreground_idle"
-        4,2950000000,50000000,"animation"
-        5,3000000000,66666674,"response"
-        6,3066666674,216666650,"animation"
-        7,3283333324,216666676,"foreground_idle"
-        8,3500000000,1000000000,"background"
-        """))
-
-  def test_modified_rail_modes_long(self):
-    return DiffTestBlueprint(
-        trace=Path('modified_rail_modes_long.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/rail_modes.sql');
-        SELECT * FROM modified_rail_slices;
-        """,
-        out=Csv("""
-        "id","ts","dur","mode"
-        2,0,1000000000,"response"
-        3,1000000000,1,"background"
-        """))
-
-  def test_modified_rail_modes_extra_long(self):
-    return DiffTestBlueprint(
-        trace=Path('modified_rail_modes_extra_long.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/rail_modes.sql');
-        SELECT * FROM modified_rail_slices;
-        """,
-        out=Csv("""
-        "id","ts","dur","mode"
-        """))
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py b/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
index fb9c9248..ed2328bd 100755
--- a/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
+++ b/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
@@ -9,30 +9,7 @@
 from python.generators.diff_tests.testing import TestSuite
 
 
-class ChromeScrollJank(TestSuite):
-  # Scroll jank metrics
-  def test_scroll_jank_general_validation(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query=Path('scroll_jank_general_validation_test.sql'),
-        out=Path('scroll_jank_general_validation.out'))
-
-  def test_scroll_jank(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/scroll_jank.sql');
-
-        SELECT
-          gesture_scroll_id,
-          trace_id,
-          jank,
-          ts,
-          dur,
-          jank_budget
-        FROM scroll_jank;
-        """,
-        out=Path('scroll_jank.out'))
+class ChromeScrollJankStdlib(TestSuite):
 
   def test_chrome_frames_with_missed_vsyncs(self):
     return DiffTestBlueprint(
@@ -61,388 +38,6 @@
         """,
         out=Path('scroll_jank_v3_percentage.out'))
 
-  def test_scroll_flow_event(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/scroll_flow_event.sql');
-
-        SELECT
-          trace_id,
-          ts,
-          dur,
-          jank,
-          step,
-          ancestor_end,
-          maybe_next_ancestor_ts,
-          next_ts,
-          next_trace_id,
-          next_step
-        FROM scroll_flow_event
-        ORDER BY gesture_scroll_id, trace_id, ts;
-        """,
-        out=Path('scroll_flow_event.out'))
-
-  def test_scroll_flow_event_general_validation(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/scroll_flow_event.sql');
-
-        SELECT
-          -- Each trace_id (in our example trace not true in general) has 8
-          -- steps. There are 139 scrolls. So we expect 1112 rows in total 72
-          -- of which are janky.
-          (
-            SELECT
-              COUNT(*)
-            FROM (
-              SELECT
-                trace_id,
-                COUNT(*)
-              FROM scroll_flow_event
-              GROUP BY trace_id
-            )
-          ) AS total_scroll_updates,
-          (
-            SELECT COUNT(*) FROM scroll_flow_event
-          ) AS total_flow_event_steps,
-          (
-            SELECT COUNT(*) FROM scroll_flow_event WHERE jank
-          ) AS total_janky_flow_event_steps,
-          (
-            SELECT COUNT(*)
-            FROM (SELECT step FROM scroll_flow_event GROUP BY step)
-          ) AS number_of_unique_steps;
-        """,
-        out=Path('scroll_flow_event_general_validation.out'))
-
-  def test_scroll_flow_event_queuing_delay(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/scroll_flow_event_queuing_delay.sql');
-
-        SELECT
-          trace_id,
-          jank,
-          step,
-          next_step,
-          ancestor_end,
-          maybe_next_ancestor_ts,
-          queuing_time_ns
-        FROM scroll_flow_event_queuing_delay
-        WHERE trace_id = 2954 OR trace_id = 2956 OR trace_id = 2960
-        ORDER BY trace_id, ts;
-        """,
-        out=Path('scroll_flow_event_queuing_delay.out'))
-
-  def test_scroll_flow_event_general_validation_2(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query=Path(
-            'scroll_flow_event_queuing_delay_general_validation_test.sql'),
-        out=Path('scroll_flow_event_general_validation.out'))
-
-  def test_scroll_jank_cause_queuing_delay(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/scroll_jank_cause_queuing_delay.sql');
-
-        SELECT
-          process_name,
-          thread_name,
-          trace_id,
-          jank,
-          dur_overlapping_ns,
-          metric_name
-        FROM scroll_jank_cause_queuing_delay
-        WHERE trace_id = 2918 OR trace_id = 2926
-        ORDER BY trace_id ASC, ts ASC;
-        """,
-        out=Path('scroll_jank_cause_queuing_delay.out'))
-
-  def test_scroll_jank_cause_queuing_delay_restricted(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/scroll_jank_cause_queuing_delay.sql');
-
-        SELECT
-          process_name,
-          thread_name,
-          trace_id,
-          jank,
-          dur_overlapping_ns,
-          restricted_metric_name
-        FROM scroll_jank_cause_queuing_delay
-        WHERE trace_id = 2918 OR trace_id = 2926
-        ORDER BY trace_id ASC, ts ASC;
-        """,
-        out=Path('scroll_jank_cause_queuing_delay_restricted.out'))
-
-  def test_scroll_jank_cause_queuing_delay_general_validation(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/scroll_jank_cause_queuing_delay.sql');
-
-        SELECT
-          COUNT(*) AS total,
-          (
-            SELECT DISTINCT
-              (avg_no_jank_dur_overlapping_ns)
-            FROM scroll_jank_cause_queuing_delay
-            WHERE
-              location = "LatencyInfo.Flow"
-              AND jank
-          ) AS janky_latency_info_non_jank_avg_dur,
-          (
-            SELECT DISTINCT
-              (avg_no_jank_dur_overlapping_ns)
-            FROM scroll_jank_cause_queuing_delay
-            WHERE
-              location = "LatencyInfo.Flow"
-              AND NOT jank
-          ) AS non_janky_latency_info_non_jank_avg_dur
-        FROM (
-          SELECT
-            trace_id
-          FROM scroll_jank_cause_queuing_delay
-          GROUP BY trace_id
-        );
-        """,
-        out=Path('scroll_jank_cause_queuing_delay_general_validation.out'))
-
-  def test_chrome_thread_slice(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_scroll_without_vsync.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/chrome_thread_slice.sql');
-
-        SELECT
-          EXTRACT_ARG(arg_set_id, 'chrome_latency_info.trace_id') AS trace_id,
-          dur,
-          thread_dur
-        FROM chrome_thread_slice
-        WHERE
-          name = 'LatencyInfo.Flow'
-          AND EXTRACT_ARG(arg_set_id, 'chrome_latency_info.trace_id') = 2734;
-        """,
-        out=Csv("""
-        "trace_id","dur","thread_dur"
-        2734,25000,25000
-        2734,1000,2000
-        2734,2000,2000
-        2734,258000,171000
-        2734,1000,1000
-        """))
-
-  def test_chrome_input_to_browser_intervals(self):
-    return DiffTestBlueprint(
-        trace=DataPath('scrolling_with_blocked_nonblocked_frames.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/chrome_input_to_browser_intervals.sql');
-
-        SELECT
-          *
-        FROM chrome_input_to_browser_intervals
-        WHERE window_start_ts >= 60934320005158
-          AND window_start_ts <= 60934338798158;
-        """,
-        out=Path('chrome_input_to_browser_intervals.out'))
-
-  def test_chrome_scroll_jank_caused_by_scheduling(self):
-    return DiffTestBlueprint(
-        trace=DataPath('fling_with_input_delay.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/chrome_scroll_jank_caused_by_scheduling.sql',
-          'dur_causes_jank_ms',
-        /* dur_causes_jank_ms = */ '5');
-
-        SELECT
-          full_name,
-          total_duration_ms,
-          total_thread_duration_ms,
-          count,
-          window_start_ts,
-          window_end_ts,
-          scroll_type
-        FROM chrome_scroll_jank_caused_by_scheduling;
-        """,
-        out=Path('chrome_scroll_jank_caused_by_scheduling_test.out'))
-
-  def test_chrome_tasks_delaying_input_processing(self):
-    return DiffTestBlueprint(
-        trace=DataPath('fling_with_input_delay.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/chrome_tasks_delaying_input_processing.sql',
-          'duration_causing_jank_ms',
-         /* duration_causing_jank_ms = */ '8');
-
-        SELECT
-          full_name,
-          duration_ms,
-          thread_dur_ms
-        FROM chrome_tasks_delaying_input_processing;
-        """,
-        out=Path('chrome_tasks_delaying_input_processing_test.out'))
-
-  def test_long_task_tracking_trace_chrome_long_tasks_delaying_input_processing(
-      self):
-    return DiffTestBlueprint(
-        trace=DataPath('long_task_tracking_trace'),
-        query="""
-        SELECT
-        RUN_METRIC('chrome/chrome_long_tasks_delaying_input_processing.sql');
-
-        SELECT
-          full_name,
-          duration_ms,
-          slice_id
-        FROM chrome_tasks_delaying_input_processing
-        ORDER BY slice_id;
-        """,
-        out=Path(
-            'long_task_tracking_trace_chrome_long_tasks_delaying_input_processing_test.out'
-        ))
-
-  # TODO(b/264520610): Uncomment once fixed
-  # chrome_long_tasks_delaying_input_processing_compare_default_test.sql
-  # long_task_tracking_trace_chrome_long_tasks_delaying_input_processing_compare_default_test.out
-  def test_experimental_reliable_chrome_tasks_delaying_input_processing(self):
-    return DiffTestBlueprint(
-        trace=DataPath('fling_with_input_delay.pftrace'),
-        query="""
-        SELECT RUN_METRIC(
-            'chrome/experimental_reliable_chrome_tasks_delaying_input_processing.sql',
-            'duration_causing_jank_ms', '8');
-
-        SELECT
-          full_name,
-          duration_ms,
-          thread_dur_ms
-        FROM chrome_tasks_delaying_input_processing;
-        """,
-        out=Path(
-            'experimental_reliable_chrome_tasks_delaying_input_processing_test.out'
-        ))
-
-  def test_chrome_scroll_inputs_per_frame(self):
-    return DiffTestBlueprint(
-        trace=DataPath('scrolling_with_blocked_nonblocked_frames.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/chrome_scroll_inputs_per_frame.sql');
-
-        SELECT
-          count_for_frame,
-          ts
-        FROM chrome_scroll_inputs_per_frame
-        WHERE ts = 60934316798158;
-        """,
-        out=Csv("""
-        "count_for_frame","ts"
-        4,60934316798158
-        """))
-
-  def test_chrome_thread_slice_repeated(self):
-    return DiffTestBlueprint(
-        trace=Path('../track_event/track_event_counters.textproto'),
-        query="""
-        SELECT RUN_METRIC('chrome/chrome_thread_slice.sql');
-
-        SELECT
-          name,
-          ts,
-          dur,
-          thread_dur
-        FROM chrome_thread_slice;
-        """,
-        out=Csv("""
-        "name","ts","dur","thread_dur"
-        "event1_on_t1",1000,100,10000
-        "event2_on_t1",2000,200,30000
-        "event3_on_t1",2000,200,10000
-        "event4_on_t1",4000,0,0
-        "float_counter_on_t1",4300,0,"[NULL]"
-        "float_counter_on_t1",4500,0,"[NULL]"
-        "event1_on_t3",4000,100,5000
-        """))
-
-  def test_frame_times_metric(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_rendering_desktop.pftrace'),
-        query=Metric('frame_times'),
-        out=Path('frame_times_metric.out'))
-
-  def test_chrome_dropped_frames_metric(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_rendering_desktop.pftrace'),
-        query=Metric('chrome_dropped_frames'),
-        out=TextProto(r"""
-        [perfetto.protos.chrome_dropped_frames]: {
-          dropped_frame: {
-            ts: 166479338462000
-            process_name: "Renderer"
-            pid: 12743
-          }
-          dropped_frame: {
-            ts: 166479355302000
-            process_name: "Renderer"
-            pid: 12743
-          }
-        }
-        """))
-
-  def test_chrome_long_latency_metric(self):
-    return DiffTestBlueprint(
-        trace=Path('../chrome/long_event_latency.textproto'),
-        query="""
-        SELECT RUN_METRIC('experimental/chrome_long_latency.sql');
-
-        SELECT * FROM long_latency_with_process_info;
-        """,
-        out=Csv("""
-        "ts","event_type","process_name","process_id"
-        200111000,"FirstGestureScrollUpdate,GestureScrollUpdate","Renderer",1001
-        200111000,"GestureScrollUpdate","Renderer",1002
-        280111001,"GestureScrollUpdate","Renderer",1001
-        """))
-
-  def test_scroll_jank_mojo_simple_watcher(self):
-    return DiffTestBlueprint(
-        trace=Path('scroll_jank_mojo_simple_watcher.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/scroll_jank_cause_queuing_delay.sql');
-
-        SELECT
-          trace_id,
-          jank,
-          dur_overlapping_ns,
-          metric_name
-        FROM scroll_jank_cause_queuing_delay
-        ORDER BY trace_id ASC, ts ASC;
-        """,
-        out=Path('scroll_jank_mojo_simple_watcher.out'))
-
-  def test_scroll_jank_gpu_check(self):
-    return DiffTestBlueprint(
-        trace=Path('scroll_jank_gpu_check.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/scroll_jank.sql');
-
-        SELECT ts, jank
-        FROM scroll_jank
-        ORDER BY ts ASC;
-        """,
-        out=Csv("""
-        "ts","jank"
-        15000000,0
-        30000000,1
-        115000000,0
-        """))
-
   def test_chrome_scrolls(self):
     return DiffTestBlueprint(
         trace=Path('chrome_scroll_check.py'),
@@ -486,48 +81,11 @@
         3,120000000,70000000
         """))
 
-  def test_chrome_scroll_jank_v3(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_input_with_frame_view.pftrace'),
-        query=Metric('chrome_scroll_jank_v3'),
-        out=TextProto(r"""
-        [perfetto.protos.chrome_scroll_jank_v3] {
-          trace_num_frames: 291
-          trace_num_janky_frames: 3
-          trace_scroll_jank_percentage: 1.0309278350515463
-          vsync_interval_ms: 16.368
-          scrolls {
-            num_frames: 105
-            num_janky_frames: 2
-            scroll_jank_percentage: 1.9047619047619047
-            max_delay_since_last_frame: 6.126221896383187
-            scroll_jank_causes {
-              cause: "RendererCompositorQueueingDelay"
-              delay_since_last_frame: 2.044354838709678
-            }
-            scroll_jank_causes {
-              cause: "RendererCompositorFinishedToBeginImplFrame"
-              delay_since_last_frame: 6.126221896383187
-            }
-          }
-          scrolls {
-            num_frames: 84
-            num_janky_frames: 1
-            scroll_jank_percentage: 1.1904761904761905
-            max_delay_since_last_frame: 2.040811339198436
-            scroll_jank_causes {
-              cause: "RendererCompositorQueueingDelay"
-              delay_since_last_frame: 2.040811339198436
-            }
-          }
-        }
-        """))
-
   def test_chrome_scroll_input_offsets(self):
     return DiffTestBlueprint(
         trace=DataPath('scroll_offsets.pftrace'),
         query="""
-        SELECT IMPORT('chrome.scroll_jank.scroll_offsets');
+        INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_offsets;
 
         SELECT
           scroll_update_id,
@@ -551,7 +109,7 @@
     return DiffTestBlueprint(
         trace=DataPath('scroll_offsets.pftrace'),
         query="""
-        SELECT IMPORT('chrome.scroll_jank.scroll_offsets');
+        INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_offsets;
 
         SELECT
           scroll_update_id,
@@ -564,9 +122,9 @@
         """,
         out=Csv("""
         "scroll_update_id","ts","delta_y","offset_y"
-        1983,4687296612739,"[NULL]",0
-        1987,4687313206739,-50,-50
-        1991,4687329240739,-50,-100
-        1993,4687336155739,-81,-181
-        1996,4687346164739,-66,-247
+        1983,4687341817739,"[NULL]",0
+        1987,4687352950739,-50,-50
+        1991,4687364083739,-50,-100
+        1993,4687375224739,-81,-181
+        1996,4687386343739,-66,-247
         """))
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/tests_touch_gesture.py b/base/tracing/test/trace_processor/diff_tests/chrome/tests_touch_gesture.py
deleted file mode 100755
index 47e1944..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/tests_touch_gesture.py
+++ /dev/null
@@ -1,134 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from python.generators.diff_tests.testing import Path, DataPath, Metric
-from python.generators.diff_tests.testing import Csv, Json, TextProto
-from python.generators.diff_tests.testing import DiffTestBlueprint
-from python.generators.diff_tests.testing import TestSuite
-
-
-class ChromeTouchGesture(TestSuite):
-
-  def test_touch_jank(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_touch_gesture_scroll.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/touch_jank.sql');
-
-        SELECT
-          touch_id,
-          trace_id,
-          jank,
-          ts,
-          dur,
-          jank_budget
-        FROM touch_jank;
-        """,
-        out=Path('touch_jank.out'))
-
-  def test_touch_flow_event(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_touch_gesture_scroll.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/touch_flow_event.sql');
-
-        SELECT
-          trace_id,
-          ts,
-          dur,
-          jank,
-          step,
-          ancestor_end,
-          maybe_next_ancestor_ts,
-          next_ts,
-          next_trace_id,
-          next_step
-        FROM touch_flow_event
-        ORDER BY touch_id, trace_id, ts;
-        """,
-        out=Path('touch_flow_event.out'))
-
-  def test_touch_flow_event_queuing_delay(self):
-    return DiffTestBlueprint(
-        trace=DataPath('chrome_touch_gesture_scroll.pftrace'),
-        query="""
-        SELECT RUN_METRIC('chrome/touch_flow_event_queuing_delay.sql');
-
-        SELECT
-          trace_id,
-          jank,
-          step,
-          next_step,
-          ancestor_end,
-          maybe_next_ancestor_ts,
-          queuing_time_ns
-        FROM touch_flow_event_queuing_delay
-        WHERE trace_id = 6915 OR trace_id = 6911 OR trace_id = 6940
-        ORDER BY trace_id, ts;
-        """,
-        out=Path('touch_flow_event_queuing_delay.out'))
-
-  def test_touch_jank_synth(self):
-    return DiffTestBlueprint(
-        trace=Path('touch_jank.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/touch_jank.sql');
-
-        SELECT
-          touch_id,
-          trace_id,
-          jank,
-          ts,
-          dur,
-          jank_budget
-        FROM touch_jank;
-        """,
-        out=Csv("""
-        "touch_id","trace_id","jank","ts","dur","jank_budget"
-        87654,34577,0,0,10000000,-31333333.350000
-        87654,34578,1,16000000,33000000,14666666.650000
-        87654,34579,0,55000000,33000000,-8333333.350000
-        """))
-
-  def test_touch_flow_event_synth(self):
-    return DiffTestBlueprint(
-        trace=Path('touch_jank.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/touch_flow_event.sql');
-
-        SELECT
-          trace_id,
-          ts,
-          dur,
-          jank,
-          step,
-          ancestor_end,
-          maybe_next_ancestor_ts,
-          next_ts,
-          next_trace_id,
-          next_step
-        FROM touch_flow_event
-        ORDER BY touch_id, trace_id, ts;
-        """,
-        out=Path('touch_flow_event_synth.out'))
-
-  def test_touch_flow_event_queuing_delay_synth(self):
-    return DiffTestBlueprint(
-        trace=Path('touch_jank.py'),
-        query="""
-        SELECT RUN_METRIC('chrome/touch_flow_event_queuing_delay.sql');
-
-        SELECT
-          trace_id,
-          jank,
-          step,
-          next_step,
-          ancestor_end,
-          maybe_next_ancestor_ts,
-          queuing_time_ns
-        FROM touch_flow_event_queuing_delay
-        ORDER BY trace_id, ts;
-        """,
-        out=Path('touch_flow_event_queuing_delay_synth.out'))
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event.out b/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event.out
deleted file mode 100644
index ae13efd..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event.out
+++ /dev/null
@@ -1,170 +0,0 @@
-
-"trace_id","ts","dur","jank","step","ancestor_end","maybe_next_ancestor_ts","next_ts","next_trace_id","next_step"
-6288,1383122421558418,226350000,1,"AsyncBegin",1383122421558418,1383122426402418,1383122426484418,6288,"Begin"
-6288,1383122426484418,11000,1,"Begin",1383122426884418,1383122426402418,1383122426625418,6288,"STEP_SEND_INPUT_EVENT_UI"
-6288,1383122426625418,237000,1,"STEP_SEND_INPUT_EVENT_UI",1383122426884418,1383122427140418,1383122427169418,6288,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6288,1383122427169418,163000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383122427336418,1383122427140418,1383122427275418,6288,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6288,1383122427275418,5000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383122427336418,1383122456261418,1383122456261418,6288,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6288,1383122456261418,37514000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383122493775418,1383122456261418,1383122493472418,6288,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6288,1383122493472418,10000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383122493775418,1383122496371418,1383122496371418,6288,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6288,1383122496371418,7000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383122496378418,1383122589999418,1383122589999418,6288,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6288,1383122589999418,24000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383122590023418,1383122601085418,1383122601085418,6288,"STEP_SWAP_BUFFERS"
-6288,1383122601085418,19000,1,"STEP_SWAP_BUFFERS",1383122601104418,1383122611053418,1383122611053418,6288,"STEP_DRAW_AND_SWAP"
-6288,1383122611053418,88000,1,"STEP_DRAW_AND_SWAP",1383122611141418,1383122647945418,1383122647945418,6288,"STEP_FINISHED_SWAP_BUFFERS"
-6288,1383122647945418,100000,1,"STEP_FINISHED_SWAP_BUFFERS",1383122648045418,"[NULL]",1383122543558418,6312,"AsyncBegin"
-6312,1383122543558418,185244000,0,"AsyncBegin",1383122543558418,1383122548583418,1383122548633418,6312,"Begin"
-6312,1383122548633418,6000,0,"Begin",1383122548862418,1383122548583418,1383122548703418,6312,"STEP_SEND_INPUT_EVENT_UI"
-6312,1383122548703418,148000,0,"STEP_SEND_INPUT_EVENT_UI",1383122548862418,1383122550407418,1383122550456418,6312,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6312,1383122550456418,364000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383122550827418,1383122550407418,1383122550719418,6312,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6312,1383122550719418,10000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383122550827418,1383122591844418,1383122591844418,6312,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6312,1383122591844418,9681000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383122601525418,1383122591844418,1383122601331418,6312,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6312,1383122601331418,9000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383122601525418,1383122603068418,1383122603068418,6312,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6312,1383122603068418,16000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383122603084418,1383122667027418,1383122667027418,6312,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6312,1383122667027418,18000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383122667045418,1383122676422418,1383122676422418,6312,"STEP_SWAP_BUFFERS"
-6312,1383122676422418,18000,0,"STEP_SWAP_BUFFERS",1383122676440418,1383122688317418,1383122688317418,6312,"STEP_DRAW_AND_SWAP"
-6312,1383122688317418,30000,0,"STEP_DRAW_AND_SWAP",1383122688347418,1383122728832418,1383122728832418,6312,"STEP_FINISHED_SWAP_BUFFERS"
-6312,1383122728832418,24000,0,"STEP_FINISHED_SWAP_BUFFERS",1383122728856418,"[NULL]",1383123604558418,6328,"AsyncBegin"
-6328,1383123604558418,207945000,1,"AsyncBegin",1383123604558418,1383123610384418,1383123610436418,6328,"Begin"
-6328,1383123610436418,7000,1,"Begin",1383123610707418,1383123610384418,1383123610515418,6328,"STEP_SEND_INPUT_EVENT_UI"
-6328,1383123610515418,181000,1,"STEP_SEND_INPUT_EVENT_UI",1383123610707418,1383123611090418,1383123611121418,6328,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6328,1383123611121418,262000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383123611387418,1383123611090418,1383123611283418,6328,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6328,1383123611283418,11000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383123611387418,1383123645509418,1383123645509418,6328,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6328,1383123645509418,9318000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383123654827418,1383123645509418,1383123654631418,6328,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6328,1383123654631418,8000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383123654827418,1383123656978418,1383123656978418,6328,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6328,1383123656978418,30000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383123657008418,1383123762642418,1383123762642418,6328,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6328,1383123762642418,13000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383123762655418,1383123768318418,1383123768318418,6328,"STEP_SWAP_BUFFERS"
-6328,1383123768318418,14000,1,"STEP_SWAP_BUFFERS",1383123768332418,1383123774132418,1383123774132418,6328,"STEP_DRAW_AND_SWAP"
-6328,1383123774132418,28000,1,"STEP_DRAW_AND_SWAP",1383123774160418,1383123812534418,1383123812534418,6328,"STEP_FINISHED_SWAP_BUFFERS"
-6328,1383123812534418,19000,1,"STEP_FINISHED_SWAP_BUFFERS",1383123812553418,"[NULL]",1383124088558418,6414,"AsyncBegin"
-6414,1383124088558418,173233000,0,"AsyncBegin",1383124088558418,1383124093797418,1383124093844418,6414,"Begin"
-6414,1383124093844418,6000,0,"Begin",1383124094081418,1383124093797418,1383124093918418,6414,"STEP_SEND_INPUT_EVENT_UI"
-6414,1383124093918418,153000,0,"STEP_SEND_INPUT_EVENT_UI",1383124094081418,1383124094617418,1383124094661418,6414,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6414,1383124094661418,320000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383124094988418,1383124094617418,1383124094887418,6414,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6414,1383124094887418,10000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383124094988418,1383124119033418,1383124119033418,6414,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6414,1383124119033418,8738000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383124127771418,1383124119033418,1383124127596418,6414,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6414,1383124127596418,7000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383124127771418,1383124127712418,1383124127712418,6414,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6414,1383124127712418,19000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383124127731418,1383124207955418,1383124207955418,6414,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6414,1383124207955418,19000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383124207974418,1383124213046418,1383124213046418,6414,"STEP_SWAP_BUFFERS"
-6414,1383124213046418,22000,0,"STEP_SWAP_BUFFERS",1383124213068418,1383124221194418,1383124221194418,6414,"STEP_DRAW_AND_SWAP"
-6414,1383124221194418,20000,0,"STEP_DRAW_AND_SWAP",1383124221214418,1383124261843418,1383124261843418,6414,"STEP_FINISHED_SWAP_BUFFERS"
-6414,1383124261843418,37000,0,"STEP_FINISHED_SWAP_BUFFERS",1383124261880418,"[NULL]",1383125521558418,6552,"AsyncBegin"
-6552,1383125521558418,161901000,0,"AsyncBegin",1383125521558418,1383125525770418,1383125525814418,6552,"Begin"
-6552,1383125525814418,6000,0,"Begin",1383125526039418,1383125525770418,1383125525888418,6552,"STEP_SEND_INPUT_EVENT_UI"
-6552,1383125525888418,141000,0,"STEP_SEND_INPUT_EVENT_UI",1383125526039418,1383125529143418,1383125529178418,6552,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6552,1383125529178418,162000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383125529344418,1383125529143418,1383125529282418,6552,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6552,1383125529282418,5000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383125529344418,1383125581612418,1383125581612418,6552,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6552,1383125581612418,12061000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383125593673418,1383125581612418,1383125593621418,6552,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6552,1383125593621418,7000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383125593673418,1383125593686418,1383125593686418,6552,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6552,1383125593686418,11000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383125593697418,1383125647723418,1383125647723418,6552,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6552,1383125647723418,23000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383125647746418,1383125654069418,1383125654069418,6552,"STEP_SWAP_BUFFERS"
-6552,1383125654069418,19000,0,"STEP_SWAP_BUFFERS",1383125654088418,1383125663282418,1383125663282418,6552,"STEP_DRAW_AND_SWAP"
-6552,1383125663282418,20000,0,"STEP_DRAW_AND_SWAP",1383125663302418,1383125683484418,1383125683484418,6552,"STEP_FINISHED_SWAP_BUFFERS"
-6552,1383125683484418,19000,0,"STEP_FINISHED_SWAP_BUFFERS",1383125683503418,"[NULL]",1383126581558418,6602,"AsyncBegin"
-6602,1383126581558418,87964000,0,"AsyncBegin",1383126581558418,1383126586079418,1383126586122418,6602,"Begin"
-6602,1383126586122418,6000,0,"Begin",1383126586328418,1383126586079418,1383126586193418,6602,"STEP_SEND_INPUT_EVENT_UI"
-6602,1383126586193418,126000,0,"STEP_SEND_INPUT_EVENT_UI",1383126586328418,1383126588328418,1383126588364418,6602,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6602,1383126588364418,821000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383126589192418,1383126588328418,1383126589084418,6602,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6602,1383126589084418,11000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383126589192418,1383126595233418,1383126595233418,6602,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6602,1383126595233418,8145000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383126603378418,1383126595233418,1383126603302418,6602,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6602,1383126603302418,7000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383126603378418,1383126603940418,1383126603940418,6602,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6602,1383126603940418,5000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383126603945418,1383126630232418,1383126630232418,6602,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6602,1383126630232418,17000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383126630249418,1383126634508418,1383126634508418,6602,"STEP_SWAP_BUFFERS"
-6602,1383126634508418,9000,0,"STEP_SWAP_BUFFERS",1383126634517418,1383126642230418,1383126642230418,6602,"STEP_DRAW_AND_SWAP"
-6602,1383126642230418,20000,0,"STEP_DRAW_AND_SWAP",1383126642250418,1383126669549418,1383126669549418,6602,"STEP_FINISHED_SWAP_BUFFERS"
-6602,1383126669549418,14000,0,"STEP_FINISHED_SWAP_BUFFERS",1383126669563418,"[NULL]",1383127076558418,6693,"AsyncBegin"
-6693,1383127076558418,140115000,1,"AsyncBegin",1383127076558418,1383127082044418,1383127082090418,6693,"Begin"
-6693,1383127082090418,7000,1,"Begin",1383127082341418,1383127082044418,1383127082166418,6693,"STEP_SEND_INPUT_EVENT_UI"
-6693,1383127082166418,164000,1,"STEP_SEND_INPUT_EVENT_UI",1383127082341418,1383127082917418,1383127082960418,6693,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6693,1383127082960418,348000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383127083315418,1383127082917418,1383127083114418,6693,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6693,1383127083114418,9000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383127083315418,1383127096393418,1383127096393418,6693,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6693,1383127096393418,7736000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383127104129418,1383127096393418,1383127104038418,6693,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6693,1383127104038418,7000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383127104129418,1383127104330418,1383127104330418,6693,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6693,1383127104330418,12000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383127104342418,1383127168839418,1383127168839418,6693,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6693,1383127168839418,36000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383127168875418,1383127175184418,1383127175184418,6693,"STEP_SWAP_BUFFERS"
-6693,1383127175184418,22000,1,"STEP_SWAP_BUFFERS",1383127175206418,1383127201828418,1383127201828418,6693,"STEP_DRAW_AND_SWAP"
-6693,1383127201828418,31000,1,"STEP_DRAW_AND_SWAP",1383127201859418,1383127216685418,1383127216685418,6693,"STEP_FINISHED_SWAP_BUFFERS"
-6693,1383127216685418,18000,1,"STEP_FINISHED_SWAP_BUFFERS",1383127216703418,"[NULL]",1383127670558418,6698,"AsyncBegin"
-6698,1383127670558418,301236000,1,"AsyncBegin",1383127670558418,1383127698512418,1383127698547418,6698,"Begin"
-6698,1383127698547418,6000,1,"Begin",1383127698732418,1383127698512418,1383127698610418,6698,"STEP_SEND_INPUT_EVENT_UI"
-6698,1383127698610418,113000,1,"STEP_SEND_INPUT_EVENT_UI",1383127698732418,1383127699155418,1383127699173418,6698,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6698,1383127699173418,196000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383127699373418,1383127699155418,1383127699323418,6698,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6698,1383127699323418,4000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383127699373418,1383127844723418,1383127844723418,6698,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6698,1383127844723418,14082000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383127858805418,1383127844723418,1383127858076418,6698,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6698,1383127858076418,7000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383127858805418,1383127861637418,1383127861637418,6698,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6698,1383127861637418,13000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383127861650418,1383127928519418,1383127928519418,6698,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6698,1383127928519418,3000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383127928522418,1383127936811418,1383127936811418,6698,"STEP_SWAP_BUFFERS"
-6698,1383127936811418,8000,1,"STEP_SWAP_BUFFERS",1383127936819418,1383127949728418,1383127949728418,6698,"STEP_DRAW_AND_SWAP"
-6698,1383127949728418,7000,1,"STEP_DRAW_AND_SWAP",1383127949735418,1383127971881418,1383127971881418,6698,"STEP_FINISHED_SWAP_BUFFERS"
-6698,1383127971881418,7000,1,"STEP_FINISHED_SWAP_BUFFERS",1383127971888418,"[NULL]",1383127837558418,6723,"AsyncBegin"
-6723,1383127837558418,134236000,0,"AsyncBegin",1383127837558418,1383127846715418,1383127846793418,6723,"Begin"
-6723,1383127846793418,11000,0,"Begin",1383127847217418,1383127846715418,1383127846940418,6723,"STEP_SEND_INPUT_EVENT_UI"
-6723,1383127846940418,255000,0,"STEP_SEND_INPUT_EVENT_UI",1383127847217418,1383127848602418,1383127848665418,6723,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6723,1383127848665418,1045000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383127849717418,1383127848602418,1383127849609418,6723,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6723,1383127849609418,12000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383127849717418,1383127874642418,1383127874642418,6723,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6723,1383127874642418,8527000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383127883169418,1383127874642418,1383127883061418,6723,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6723,1383127883061418,8000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383127883169418,1383127885270418,1383127885270418,6723,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6723,1383127885270418,14000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383127885284418,1383127928530418,1383127928530418,6723,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6723,1383127928530418,3000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383127928533418,1383127936838418,1383127936838418,6723,"STEP_SWAP_BUFFERS"
-6723,1383127936838418,8000,0,"STEP_SWAP_BUFFERS",1383127936846418,1383127949753418,1383127949753418,6723,"STEP_DRAW_AND_SWAP"
-6723,1383127949753418,7000,0,"STEP_DRAW_AND_SWAP",1383127949760418,1383127971906418,1383127971906418,6723,"STEP_FINISHED_SWAP_BUFFERS"
-6723,1383127971906418,7000,0,"STEP_FINISHED_SWAP_BUFFERS",1383127971913418,"[NULL]",1383129053558418,6802,"AsyncBegin"
-6802,1383129053558418,163272000,0,"AsyncBegin",1383129053558418,1383129081907418,1383129081950418,6802,"Begin"
-6802,1383129081950418,46000,0,"Begin",1383129082214418,1383129081907418,1383129082066418,6802,"STEP_SEND_INPUT_EVENT_UI"
-6802,1383129082066418,138000,0,"STEP_SEND_INPUT_EVENT_UI",1383129082214418,1383129082616418,1383129082657418,6802,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6802,1383129082657418,782000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383129083446418,1383129082616418,1383129083335418,6802,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6802,1383129083335418,10000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383129083446418,1383129105125418,1383129105125418,6802,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6802,1383129105125418,6978000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383129112103418,1383129105125418,1383129111999418,6802,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6802,1383129111999418,8000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383129112103418,1383129113877418,1383129113877418,6802,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6802,1383129113877418,12000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383129113889418,1383129155519418,1383129155519418,6802,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6802,1383129155519418,18000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383129155537418,1383129177753418,1383129177753418,6802,"STEP_SWAP_BUFFERS"
-6802,1383129177753418,30000,0,"STEP_SWAP_BUFFERS",1383129177783418,1383129181587418,1383129181587418,6802,"STEP_DRAW_AND_SWAP"
-6802,1383129181587418,21000,0,"STEP_DRAW_AND_SWAP",1383129181608418,1383129216866418,1383129216866418,6802,"STEP_FINISHED_SWAP_BUFFERS"
-6802,1383129216866418,29000,0,"STEP_FINISHED_SWAP_BUFFERS",1383129216895418,"[NULL]",1383129492558418,6877,"AsyncBegin"
-6877,1383129492558418,370407000,1,"AsyncBegin",1383129492558418,1383129497787418,1383129497859418,6877,"Begin"
-6877,1383129497859418,11000,1,"Begin",1383129498184418,1383129497787418,1383129497995418,6877,"STEP_SEND_INPUT_EVENT_UI"
-6877,1383129497995418,168000,1,"STEP_SEND_INPUT_EVENT_UI",1383129498184418,1383129498483418,1383129498503418,6877,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6877,1383129498503418,329000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383129498836418,1383129498483418,1383129498775418,6877,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6877,1383129498775418,5000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383129498836418,1383129719266418,1383129719266418,6877,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6877,1383129719266418,24639000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383129743905418,1383129719266418,1383129742223418,6877,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6877,1383129742223418,13000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383129743905418,1383129743178418,1383129743178418,6877,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6877,1383129743178418,12000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383129743190418,1383129816012418,1383129816012418,6877,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6877,1383129816012418,18000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383129816030418,1383129823726418,1383129823726418,6877,"STEP_SWAP_BUFFERS"
-6877,1383129823726418,46000,1,"STEP_SWAP_BUFFERS",1383129823772418,1383129835535418,1383129835535418,6877,"STEP_DRAW_AND_SWAP"
-6877,1383129835535418,18000,1,"STEP_DRAW_AND_SWAP",1383129835553418,1383129863003418,1383129863003418,6877,"STEP_FINISHED_SWAP_BUFFERS"
-6877,1383129863003418,30000,1,"STEP_FINISHED_SWAP_BUFFERS",1383129863033418,"[NULL]",1383130519558418,6911,"AsyncBegin"
-6911,1383130519558418,198057000,1,"AsyncBegin",1383130519558418,1383130544003418,1383130544042418,6911,"Begin"
-6911,1383130544042418,7000,1,"Begin",1383130544237418,1383130544003418,1383130544113418,6911,"STEP_SEND_INPUT_EVENT_UI"
-6911,1383130544113418,115000,1,"STEP_SEND_INPUT_EVENT_UI",1383130544237418,1383130546898418,1383130546932418,6911,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6911,1383130546932418,833000,1,"STEP_HANDLE_INPUT_EVENT_IMPL",1383130547772418,1383130546898418,1383130547581418,6911,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6911,1383130547581418,10000,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130547772418,1383130555182418,1383130555182418,6911,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6911,1383130555182418,18263000,1,"STEP_HANDLE_INPUT_EVENT_MAIN",1383130573445418,1383130555182418,1383130573221418,6911,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6911,1383130573221418,12000,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130573445418,1383130573311418,1383130573311418,6911,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6911,1383130573311418,10000,1,"STEP_HANDLED_INPUT_EVENT_IMPL",1383130573321418,1383130656314418,1383130656314418,6911,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6911,1383130656314418,11000,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130656325418,1383130667367418,1383130667367418,6911,"STEP_SWAP_BUFFERS"
-6911,1383130667367418,17000,1,"STEP_SWAP_BUFFERS",1383130667384418,1383130681350418,1383130681350418,6911,"STEP_DRAW_AND_SWAP"
-6911,1383130681350418,25000,1,"STEP_DRAW_AND_SWAP",1383130681375418,1383130717639418,1383130717639418,6911,"STEP_FINISHED_SWAP_BUFFERS"
-6911,1383130717639418,18000,1,"STEP_FINISHED_SWAP_BUFFERS",1383130717657418,"[NULL]",1383130553558418,6915,"AsyncBegin"
-6915,1383130553558418,164057000,0,"AsyncBegin",1383130553558418,1383130558151418,1383130558197418,6915,"Begin"
-6915,1383130558197418,6000,0,"Begin",1383130558425418,1383130558151418,1383130558273418,6915,"STEP_SEND_INPUT_EVENT_UI"
-6915,1383130558273418,141000,0,"STEP_SEND_INPUT_EVENT_UI",1383130558425418,1383130558645418,1383130558675418,6915,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6915,1383130558675418,155000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383130558834418,1383130558645418,1383130558779418,6915,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6915,1383130558779418,4000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130558834418,1383130587655418,1383130587655418,6915,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6915,1383130587655418,7138000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383130594793418,1383130587655418,1383130594603418,6915,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6915,1383130594603418,6000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130594793418,1383130594791418,1383130594791418,6915,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6915,1383130594791418,20000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383130594811418,1383130656335418,1383130656335418,6915,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6915,1383130656335418,4000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130656339418,1383130667392418,1383130667392418,6915,"STEP_SWAP_BUFFERS"
-6915,1383130667392418,3000,0,"STEP_SWAP_BUFFERS",1383130667395418,1383130681397418,1383130681397418,6915,"STEP_DRAW_AND_SWAP"
-6915,1383130681397418,7000,0,"STEP_DRAW_AND_SWAP",1383130681404418,1383130717665418,1383130717665418,6915,"STEP_FINISHED_SWAP_BUFFERS"
-6915,1383130717665418,3000,0,"STEP_FINISHED_SWAP_BUFFERS",1383130717668418,"[NULL]",1383130681558418,6940,"AsyncBegin"
-6940,1383130681558418,167758000,0,"AsyncBegin",1383130681558418,1383130686495418,1383130686567418,6940,"Begin"
-6940,1383130686567418,13000,0,"Begin",1383130686909418,1383130686495418,1383130686705418,6940,"STEP_SEND_INPUT_EVENT_UI"
-6940,1383130686705418,184000,0,"STEP_SEND_INPUT_EVENT_UI",1383130686909418,1383130687055418,1383130687081418,6940,"STEP_HANDLE_INPUT_EVENT_IMPL"
-6940,1383130687081418,334000,0,"STEP_HANDLE_INPUT_EVENT_IMPL",1383130687419418,1383130687055418,1383130687360418,6940,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL"
-6940,1383130687360418,5000,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130687419418,1383130719656418,1383130719656418,6940,"STEP_HANDLE_INPUT_EVENT_MAIN"
-6940,1383130719656418,8298000,0,"STEP_HANDLE_INPUT_EVENT_MAIN",1383130727954418,1383130719656418,1383130727856418,6940,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL"
-6940,1383130727856418,7000,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130727954418,1383130728343418,1383130728343418,6940,"STEP_HANDLED_INPUT_EVENT_IMPL"
-6940,1383130728343418,13000,0,"STEP_HANDLED_INPUT_EVENT_IMPL",1383130728356418,1383130815135418,1383130815135418,6940,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT"
-6940,1383130815135418,19000,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130815154418,1383130825051418,1383130825051418,6940,"STEP_SWAP_BUFFERS"
-6940,1383130825051418,35000,0,"STEP_SWAP_BUFFERS",1383130825086418,1383130834387418,1383130834387418,6940,"STEP_DRAW_AND_SWAP"
-6940,1383130834387418,18000,0,"STEP_DRAW_AND_SWAP",1383130834405418,1383130849338418,1383130849338418,6940,"STEP_FINISHED_SWAP_BUFFERS"
-6940,1383130849338418,17000,0,"STEP_FINISHED_SWAP_BUFFERS",1383130849355418,"[NULL]","[NULL]","[NULL]","[NULL]"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event_queuing_delay.out b/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event_queuing_delay.out
deleted file mode 100644
index aa26ef67..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event_queuing_delay.out
+++ /dev/null
@@ -1,38 +0,0 @@
-
-"trace_id","jank","step","next_step","ancestor_end","maybe_next_ancestor_ts","queuing_time_ns"
-6911,1,"AsyncBegin","Begin",1383130519558418,1383130544003418,24445000
-6911,1,"Begin","STEP_SEND_INPUT_EVENT_UI",1383130544237418,1383130544003418,0
-6911,1,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",1383130544237418,1383130546898418,2661000
-6911,1,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130547772418,1383130546898418,0
-6911,1,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_HANDLE_INPUT_EVENT_MAIN",1383130547772418,1383130555182418,7410000
-6911,1,"STEP_HANDLE_INPUT_EVENT_MAIN","STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130573445418,1383130555182418,0
-6911,1,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL","STEP_HANDLED_INPUT_EVENT_IMPL",1383130573445418,1383130573311418,0
-6911,1,"STEP_HANDLED_INPUT_EVENT_IMPL","STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130573321418,1383130656314418,82993000
-6911,1,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT","STEP_SWAP_BUFFERS",1383130656325418,1383130667367418,11042000
-6911,1,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",1383130667384418,1383130681350418,13966000
-6911,1,"STEP_DRAW_AND_SWAP","STEP_FINISHED_SWAP_BUFFERS",1383130681375418,1383130717639418,36264000
-6911,1,"STEP_FINISHED_SWAP_BUFFERS","AsyncBegin",1383130717657418,"[NULL]","[NULL]"
-6915,0,"AsyncBegin","Begin",1383130553558418,1383130558151418,4593000
-6915,0,"Begin","STEP_SEND_INPUT_EVENT_UI",1383130558425418,1383130558151418,0
-6915,0,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",1383130558425418,1383130558645418,220000
-6915,0,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130558834418,1383130558645418,0
-6915,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_HANDLE_INPUT_EVENT_MAIN",1383130558834418,1383130587655418,28821000
-6915,0,"STEP_HANDLE_INPUT_EVENT_MAIN","STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130594793418,1383130587655418,0
-6915,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL","STEP_HANDLED_INPUT_EVENT_IMPL",1383130594793418,1383130594791418,0
-6915,0,"STEP_HANDLED_INPUT_EVENT_IMPL","STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130594811418,1383130656335418,61524000
-6915,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT","STEP_SWAP_BUFFERS",1383130656339418,1383130667392418,11053000
-6915,0,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",1383130667395418,1383130681397418,14002000
-6915,0,"STEP_DRAW_AND_SWAP","STEP_FINISHED_SWAP_BUFFERS",1383130681404418,1383130717665418,36261000
-6915,0,"STEP_FINISHED_SWAP_BUFFERS","AsyncBegin",1383130717668418,"[NULL]","[NULL]"
-6940,0,"AsyncBegin","Begin",1383130681558418,1383130686495418,4937000
-6940,0,"Begin","STEP_SEND_INPUT_EVENT_UI",1383130686909418,1383130686495418,0
-6940,0,"STEP_SEND_INPUT_EVENT_UI","STEP_HANDLE_INPUT_EVENT_IMPL",1383130686909418,1383130687055418,146000
-6940,0,"STEP_HANDLE_INPUT_EVENT_IMPL","STEP_DID_HANDLE_INPUT_AND_OVERSCROLL",1383130687419418,1383130687055418,0
-6940,0,"STEP_DID_HANDLE_INPUT_AND_OVERSCROLL","STEP_HANDLE_INPUT_EVENT_MAIN",1383130687419418,1383130719656418,32237000
-6940,0,"STEP_HANDLE_INPUT_EVENT_MAIN","STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL",1383130727954418,1383130719656418,0
-6940,0,"STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL","STEP_HANDLED_INPUT_EVENT_IMPL",1383130727954418,1383130728343418,389000
-6940,0,"STEP_HANDLED_INPUT_EVENT_IMPL","STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT",1383130728356418,1383130815135418,86779000
-6940,0,"STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT","STEP_SWAP_BUFFERS",1383130815154418,1383130825051418,9897000
-6940,0,"STEP_SWAP_BUFFERS","STEP_DRAW_AND_SWAP",1383130825086418,1383130834387418,9301000
-6940,0,"STEP_DRAW_AND_SWAP","STEP_FINISHED_SWAP_BUFFERS",1383130834405418,1383130849338418,14933000
-6940,0,"STEP_FINISHED_SWAP_BUFFERS","[NULL]",1383130849355418,"[NULL]","[NULL]"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event_queuing_delay_synth.out b/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event_queuing_delay_synth.out
deleted file mode 100644
index 7c5c8b0..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event_queuing_delay_synth.out
+++ /dev/null
@@ -1,12 +0,0 @@
-
-"trace_id","jank","step","next_step","ancestor_end","maybe_next_ancestor_ts","queuing_time_ns"
-34577,0,"AsyncBegin","Begin",0,0,0
-34577,0,"Begin","End",1000000,11000000,10000000
-34577,0,"End","AsyncBegin",12000000,"[NULL]","[NULL]"
-34578,1,"AsyncBegin","Begin",16000000,16000000,0
-34578,1,"Begin","End",17000000,50000000,33000000
-34578,1,"End","AsyncBegin",51000000,"[NULL]","[NULL]"
-34579,0,"AsyncBegin","Begin",55000000,55000000,0
-34579,0,"Begin","STEP_SEND_INPUT_EVENT_UI",56000000,87000000,31000000
-34579,0,"STEP_SEND_INPUT_EVENT_UI","End",88000000,89000000,1000000
-34579,0,"End","[NULL]",90000000,"[NULL]","[NULL]"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event_synth.out b/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event_synth.out
deleted file mode 100644
index 570f3c0..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/touch_flow_event_synth.out
+++ /dev/null
@@ -1,12 +0,0 @@
-
-"trace_id","ts","dur","jank","step","ancestor_end","maybe_next_ancestor_ts","next_ts","next_trace_id","next_step"
-34577,0,10000000,0,"AsyncBegin",0,0,0,34577,"Begin"
-34577,0,1000000,0,"Begin",1000000,11000000,11000000,34577,"End"
-34577,11000000,1000000,0,"End",12000000,"[NULL]",16000000,34578,"AsyncBegin"
-34578,16000000,33000000,1,"AsyncBegin",16000000,16000000,16000000,34578,"Begin"
-34578,16000000,1000000,1,"Begin",17000000,50000000,50000000,34578,"End"
-34578,50000000,1000000,1,"End",51000000,"[NULL]",55000000,34579,"AsyncBegin"
-34579,55000000,33000000,0,"AsyncBegin",55000000,55000000,55000000,34579,"Begin"
-34579,55000000,1000000,0,"Begin",56000000,87000000,87000000,34579,"STEP_SEND_INPUT_EVENT_UI"
-34579,87000000,1000000,0,"STEP_SEND_INPUT_EVENT_UI",88000000,89000000,89000000,34579,"End"
-34579,89000000,1000000,0,"End",90000000,"[NULL]","[NULL]","[NULL]","[NULL]"
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/touch_jank.out b/base/tracing/test/trace_processor/diff_tests/chrome/touch_jank.out
deleted file mode 100644
index 18edb3f..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/touch_jank.out
+++ /dev/null
@@ -1,16 +0,0 @@
-
-"touch_id","trace_id","jank","ts","dur","jank_budget"
-6280,6288,1,1383122421558418,226350000,32772666.650000
-6280,6312,0,1383122543558418,185244000,-31034333.350000
-6318,6328,1,1383123604558418,207945000,26378666.650000
-6318,6414,0,1383124088558418,173233000,2998666.650000
-6420,6552,0,1383125521558418,161901000,65603666.650000
-6586,6602,0,1383126581558418,87964000,-60484333.350000
-6586,6693,1,1383127076558418,140115000,43817666.650000
-6697,6698,1,1383127670558418,301236000,158666666.650000
-6697,6723,0,1383127837558418,134236000,-37369333.350000
-6788,6802,0,1383129053558418,163272000,20702666.650000
-6788,6877,1,1383129492558418,370407000,198801666.650000
-6906,6911,1,1383130519558418,198057000,25666666.650000
-6906,6915,0,1383130553558418,164057000,-12034333.350000
-6906,6940,0,1383130681558418,167758000,-4632333.350000
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/touch_jank.py b/base/tracing/test/trace_processor/diff_tests/chrome/touch_jank.py
deleted file mode 100755
index 76b1edd..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/touch_jank.py
+++ /dev/null
@@ -1,176 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2023 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This is intended to test the handling of simple_watcher style mojo events,
-# which are often missing trace events below them and so are all aggregated
-# together despite them coming into different mojo interfaces.
-
-from os import sys
-
-import synth_common
-
-from synth_common import ms_to_ns
-trace = synth_common.create_trace()
-
-process_track1 = 1234
-
-trace.add_process_track_descriptor(process_track1, pid=0)
-
-process_pid1 = 2345
-
-thread_track1 = 1235
-
-# Main threads have the same ID as the process
-thread_tid1 = process_pid1
-
-seq1 = 9876
-
-thread1_counter = 60
-
-touch_move_trace_id = 34576
-trace_id1 = touch_move_trace_id + 1
-trace_id2 = trace_id1 + 1
-trace_id3 = trace_id2 + 1
-touch_end_trace_id = trace_id3 + 1
-
-touch_gesture_id = 87654
-
-flow_id1 = 45678
-flow_id2 = 45679
-flow_id3 = 45680
-
-trace.add_input_latency_event_slice(
-    "TouchStart",
-    ts=ms_to_ns(0),
-    dur=ms_to_ns(1),
-    track=touch_move_trace_id,
-    trace_id=touch_move_trace_id,
-    touch_id=touch_gesture_id)
-
-trace.add_chrome_process_track_descriptor(process_track1, process_pid1)
-
-trace.add_chrome_thread_with_cpu_counter(
-    process_track1,
-    thread_track1,
-    trusted_packet_sequence_id=seq1,
-    counter_track=thread1_counter,
-    pid=process_pid1,
-    tid=thread_tid1,
-    thread_type=trace.prototypes.ThreadDescriptor.ChromeThreadType
-    .CHROME_THREAD_MAIN)
-
-# Touch move 1 - not janky
-trace.add_input_latency_event_slice(
-    "TouchMove",
-    ts=ms_to_ns(0),
-    dur=ms_to_ns(10),
-    track=trace_id1,
-    trace_id=trace_id1,
-    touch_id=touch_gesture_id,
-    is_coalesced=0)
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(0),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id1,
-    flow_ids=[flow_id1])
-
-# The slices below will block this "not janky" touch move 1.
-trace.add_track_event_slice(
-    "task", ts=ms_to_ns(2), dur=ms_to_ns(6), trusted_sequence_id=seq1)
-
-trace.add_track_event_slice(
-    "subtask", ts=ms_to_ns(3), dur=ms_to_ns(4), trusted_sequence_id=seq1)
-# This ends the blocking slices of "not janky" touch move 1.
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(11),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id1,
-    terminating_flow_ids=[flow_id1])
-
-# Touch move 2 - janky
-trace.add_input_latency_event_slice(
-    "TouchMove",
-    ts=ms_to_ns(16),
-    dur=ms_to_ns(33),
-    track=trace_id2,
-    trace_id=trace_id2,
-    touch_id=touch_gesture_id,
-    is_coalesced=0)
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(16),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id2,
-    flow_ids=[flow_id2])
-
-# The slices below will block this "janky" touch move 2.
-trace.add_track_event_slice(
-    "task", ts=ms_to_ns(18), dur=ms_to_ns(29), trusted_sequence_id=seq1)
-
-trace.add_track_event_slice(
-    "subtask", ts=ms_to_ns(19), dur=ms_to_ns(27), trusted_sequence_id=seq1)
-# This ends the blocking slices of "janky" touch move 2.
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(50),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id2,
-    terminating_flow_ids=[flow_id2])
-
-# Touch move 3 - janky
-trace.add_input_latency_event_slice(
-    "TouchMove",
-    ts=ms_to_ns(55),
-    dur=ms_to_ns(33),
-    track=trace_id3,
-    trace_id=trace_id3,
-    touch_id=touch_gesture_id,
-    is_coalesced=0)
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(55),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id3,
-    flow_ids=[flow_id3])
-
-# The slices below will block this "janky" touch move 3.
-trace.add_track_event_slice(
-    "task", ts=ms_to_ns(57), dur=ms_to_ns(29), trusted_sequence_id=seq1)
-
-packet = trace.add_track_event_slice(
-    "subtask", ts=ms_to_ns(58), dur=ms_to_ns(27), trusted_sequence_id=seq1)
-# This ends the blocking slices of "janky" touch move 3.
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(87),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id3,
-    step=trace.prototypes.ChromeLatencyInfo.Step.STEP_SEND_INPUT_EVENT_UI,
-    terminating_flow_ids=[flow_id3])
-
-trace.add_latency_info_flow(
-    ts=ms_to_ns(89),
-    dur=ms_to_ns(1),
-    trusted_sequence_id=seq1,
-    trace_id=trace_id3,
-    terminating_flow_ids=[flow_id3])
-
-trace.add_input_latency_event_slice(
-    "TouchEnd",
-    ts=ms_to_ns(90),
-    dur=ms_to_ns(2),
-    track=touch_end_trace_id,
-    trace_id=touch_end_trace_id,
-    touch_id=touch_gesture_id)
-
-sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/base/tracing/test/trace_processor/diff_tests/chrome/unsymbolized_args.textproto b/base/tracing/test/trace_processor/diff_tests/chrome/unsymbolized_args.textproto
deleted file mode 100644
index 75e21de..0000000
--- a/base/tracing/test/trace_processor/diff_tests/chrome/unsymbolized_args.textproto
+++ /dev/null
@@ -1,118 +0,0 @@
-packet {
-  incremental_state_cleared: true
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  interned_data {
-    mapping_paths {
-      iid: 1
-      str: "liblib.so"
-    }
-    mapping_paths {
-        iid: 2
-        str: "libmonochrome_64.so"
-    }
-    build_ids {
-      iid: 2
-      str: "build-id"
-    }
-    # This build id has to have a specific format to test ELF->Breakpad
-    # demangling. Taken from
-    # test/trace_processor/profiling/heap_profile_no_symbols.textproto
-    build_ids {
-        iid: 3
-        str: "\x7f\x07\x15\xc2\x86\xf8\xb1\x6c\x10\xe4\xad\x34\x9c\xda\x3b\x9b\x56\xc7\xa7\x73"
-    }
-    mappings {
-        iid: 1
-        path_string_ids: 1
-        build_id: 2
-    }
-    mappings {
-        iid: 2
-        path_string_ids: 2
-        build_id: 3
-    }
-    unsymbolized_source_locations {
-        iid: 1
-        mapping_id: 1
-        rel_pc: 123
-    }
-    unsymbolized_source_locations {
-        iid: 2
-        mapping_id: 2
-        rel_pc: 234
-    }
-  }
-}
-# Track for slice begin/end events.
-packet {
-  timestamp: 0
-  trusted_packet_sequence_id: 1
-  track_descriptor {
-    uuid: 12345
-    thread {
-      pid: 123
-      tid: 345
-    }
-    parent_uuid: 0
-    chrome_thread {
-      thread_type: THREAD_POOL_FG_WORKER
-    }
-  }
-}
-
-# Slice begin with mojo arg
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 10
-  track_event {
-    track_uuid: 12345
-    categories: "cat1"
-    type: 1
-    name: "slice1"
-    chrome_mojo_event_info {
-        mojo_interface_method_iid: 1
-    }
-  }
-}
-
-# Another slice begin with mojo arg
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 11
-  track_event {
-    track_uuid: 12345
-    categories: "cat1"
-    type: 1
-    name: "slice2"
-    chrome_mojo_event_info {
-        mojo_interface_method_iid: 2
-    }
-  }
-}
-
-
-# Second slice end
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 6000
-  track_event {
-    track_uuid: 12345
-    categories: "cat1"
-    name: "slice2"
-    type: 2
-  }
-}
-
-# First slice end
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 6001
-  track_event {
-    track_uuid: 12345
-    categories: "cat1"
-    name: "slice1"
-    type: 2
-  }
-}
\ No newline at end of file
diff --git a/base/tracing/test/trace_processor/diff_tests/include_index.py b/base/tracing/test/trace_processor/diff_tests/include_index.py
index fdd8290..20ab1c6 100755
--- a/base/tracing/test/trace_processor/diff_tests/include_index.py
+++ b/base/tracing/test/trace_processor/diff_tests/include_index.py
@@ -6,22 +6,13 @@
 from typing import List
 
 from python.generators.diff_tests import testing
-from chrome.tests import Chrome
-from chrome.tests_scroll_jank import ChromeScrollJank
-from chrome.tests_args import ChromeArgs
-from chrome.tests_memory_snapshots import ChromeMemorySnapshots
-from chrome.tests_processes import ChromeProcesses
-from chrome.tests_rail_modes import ChromeRailModes
-from chrome.tests_touch_gesture import ChromeTouchGesture
+from chrome.tests import ChromeStdlib
+from chrome.tests_scroll_jank import ChromeScrollJankStdlib
+from chrome.tests_chrome_interactions import ChromeInteractions
 
 def fetch_all_diff_tests(index_path: str) -> List['testing.TestCase']:
   return [
-      *ChromeScrollJank(index_path, 'chrome', 'ChromeScrollJank').fetch(),
-      *Chrome(index_path, 'chrome', 'Chrome').fetch(),
-      *ChromeArgs(index_path, 'chrome', 'ChromeArgs').fetch(),
-      *ChromeMemorySnapshots(index_path, 'chrome', 'ChromeMemorySnapshots')
-              .fetch(),
-      *ChromeProcesses(index_path, 'chrome', 'ChromeProcesses').fetch(),
-      *ChromeRailModes(index_path, 'chrome', 'ChromeRailModes').fetch(),
-      *ChromeTouchGesture(index_path, 'chrome', 'ChromeTouchGesture').fetch(),
+      *ChromeScrollJankStdlib(index_path, 'chrome', 'ChromeScrollJank').fetch(),
+      *ChromeStdlib(index_path, 'chrome', 'Chrome').fetch(),
+      *ChromeInteractions(index_path, 'chrome', 'ChromeInteractions').fetch(),
       ]
diff --git a/base/tracing/test/trace_processor/diff_tests/track_event/track_event_counters.textproto b/base/tracing/test/trace_processor/diff_tests/track_event/track_event_counters.textproto
deleted file mode 100644
index 6fe3b59..0000000
--- a/base/tracing/test/trace_processor/diff_tests/track_event/track_event_counters.textproto
+++ /dev/null
@@ -1,335 +0,0 @@
-# Sequence 1 defaults to track for "t1" and extra_counter_values for "c1".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    parent_uuid: 3
-    thread {
-      pid: 5
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 1
-      extra_counter_track_uuids: 10  # Counter "c1", defined below.
-    }
-  }
-}
-
-# Process track for the thread.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 3
-    process {
-      pid: 5
-      process_name: "Browser"
-    }
-    chrome_process {}
-  }
-}
-
-# Counter track "c1", a thread-scoped counter for "t1".
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 0
-  track_descriptor {
-    uuid: 10
-    parent_uuid: 1
-    counter {
-      type: 1                # COUNTER_THREAD_TIME_NS.
-      unit_multiplier: 1000  # provided in ys.
-      is_incremental: true   # use delta encoding.
-    }
-  }
-}
-
-# Sequence 2 has no defaults. Define a new global counter "MySizeCounter".
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 11
-    name: "MySizeCounter"
-    counter {
-      unit: 3  # UNIT_SIZE_BYTES.
-    }
-  }
-}
-
-# Should appear on default track "t1" with extra_counter_values for "c1".
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 1000
-  track_event {
-    categories: "cat"
-    name: "event1_on_t1"
-    type: 1                     # TYPE_SLICE_BEGIN.
-    extra_counter_values: 1000  # First value, so effectively absolute.
-  }
-}
-
-# End for event above.
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 1100
-  track_event {
-    type: 2                   # TYPE_SLICE_END.
-    extra_counter_values: 10  # Absolute: 1010.
-  }
-}
-
-# Resetting incremental state on sequence 1 will restart counter at 0.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 2000
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 1
-    parent_uuid: 3
-    thread {
-      pid: 5
-      tid: 1
-      thread_name: "t1"
-    }
-  }
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 1
-      extra_counter_track_uuids: 10  # Counter "c1", defined below.
-    }
-  }
-}
-
-# Reemit process track for the thread.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 2000
-  track_descriptor {
-    uuid: 3
-    process {
-      pid: 5
-      process_name: "Browser"
-    }
-  }
-}
-
-# Reemit counter descriptor, too.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 2000
-  track_descriptor {
-    uuid: 10
-    parent_uuid: 1
-    counter {
-      type: 1                # COUNTER_THREAD_TIME_NS.
-      unit_multiplier: 1000  # provided in us.
-      is_incremental: true   # use delta encoding.
-    }
-  }
-}
-
-# Should appear on default track "t1" with extra_counter_values for "c1".
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 2000
-  track_event {
-    categories: "cat"
-    name: "event2_on_t1"
-    type: 1                     # TYPE_SLICE_BEGIN.
-    extra_counter_values: 2000  # First value after reset, so absolute.
-  }
-}
-
-# Nested value that happens to be emitted at the same timestamp but different
-# thread time value.
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 2000
-  track_event {
-    categories: "cat"
-    name: "event3_on_t1"
-    type: 1                     # TYPE_SLICE_BEGIN.
-    extra_counter_values: 10    # Absolute: 2010
-  }
-}
-
-# End for event above.
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 2200
-  track_event {
-    type: 2                   # TYPE_SLICE_END.
-    extra_counter_values: 10  # Absolute: 2020.
-  }
-}
-
-# End for event for "event2_on_t1".
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 2200
-  track_event {
-    type: 2                   # TYPE_SLICE_END.
-    extra_counter_values: 10  # Absolute: 2030.
-  }
-}
-
-# Counter type event for "MySizeCounter" on sequence 1.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 3000
-  track_event {
-    track_uuid: 11       # "MySizeCounter".
-    type: 4              # TYPE_COUNTER.
-    counter_value: 1024  # Absolute.
-  }
-}
-
-# Counter type event for "MySizeCounter" on sequence 2.
-packet {
-  trusted_packet_sequence_id: 2
-  timestamp: 3100
-  track_event {
-    track_uuid: 11       # "MySizeCounter".
-    type: 4              # TYPE_COUNTER.
-    counter_value: 2048  # Absolute.
-  }
-}
-
-# Override the default extra_counter_values.
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 4000
-  track_event {
-    categories: "cat"
-    name: "event4_on_t1"
-    type: 3                        # TYPE_INSTANT.
-    extra_counter_track_uuids: 10  # "c1".
-    extra_counter_track_uuids: 11  # "MySizeCounter".
-    extra_counter_values: 10       # Absolute: 2040.
-    extra_counter_values: 1024     # Absolute: 2040.
-  }
-}
-
-# Sequence 3 defaults to track for "t4" and uses legacy thread time and
-# instruction count.
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 0
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 4
-    parent_uuid: 3
-    thread {
-      pid: 5
-      tid: 4
-      thread_name: "t4"
-    }
-  }
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 4
-    }
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 4000
-  track_event {
-    categories: "cat"
-    name: "event1_on_t3"
-    type: 1                        # TYPE_SLICE_BEGIN.
-    thread_time_absolute_us: 10
-    thread_instruction_count_absolute: 20
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 3
-  timestamp: 4100
-  track_event {
-    categories: "cat"
-    name: "event1_on_t3"
-    type: 2                        # TYPE_SLICE_END.
-    thread_time_absolute_us: 15
-    thread_instruction_count_absolute: 25
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 4200
-  incremental_state_cleared: true
-  track_descriptor {
-    uuid: 12
-    name: "MyDoubleCounter"
-    counter {
-    }
-  }
-}
-
-# Floating point counter value.
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 4200
-  track_event {
-    track_uuid: 12                   # "MyDoubleCounter".
-    type: 4                          # TYPE_COUNTER.
-    double_counter_value: 3.1415926  # Floating point.
-  }
-}
-
-# Floating point extra counter value.
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 4300
-  track_event {
-    categories: "cat"
-    name: "float_counter_on_t1"
-    type: 3                               # TYPE_INSTANT.
-    extra_double_counter_track_uuids: 12  # "MyDoubleCounter".
-    extra_double_counter_values: 0.5
-  }
-}
-
-# Floating point extra counter value with sequence defaults (used together with
-# an integer counter).
-packet {
-  trusted_packet_sequence_id: 1
-  timestamp: 4400
-  trace_packet_defaults {
-    track_event_defaults {
-      track_uuid: 1
-      extra_counter_track_uuids: 11         # "MySizeCounter"
-      extra_double_counter_track_uuids: 12  # "MyDoubleCounter"
-    }
-  }
-}
-
-packet {
-  trusted_packet_sequence_id: 1
-  sequence_flags: 2  # SEQ_NEEDS_INCREMENTAL_STATE
-  timestamp: 4500
-  track_event {
-    categories: "cat"
-    name: "float_counter_on_t1"
-    type: 3                        # TYPE_INSTANT.
-    extra_counter_values: 4096
-    extra_double_counter_values: 2.71828
-  }
-}
\ No newline at end of file
diff --git a/build/BUILD.gn b/build/BUILD.gn
index bd0f645..fc551fa1 100644
--- a/build/BUILD.gn
+++ b/build/BUILD.gn
@@ -3,8 +3,8 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/chromeos/args.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 6fb4954..f3416871 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -3,8 +3,8 @@
 # found in the LICENSE file.
 
 import("//build/config/c++/c++.gni")
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/dcheck_always_on.gni")
 import("//build/config/features.gni")
 
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index d244f96..f9115ca 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -26,7 +26,7 @@
 # toolchains. Checking |is_android| here would therefore be too restrictive.
 if (is_android || is_chromeos) {
   import("//build/config/android/channel.gni")
-  import("//build/config/chromecast_build.gni")
+  import("//build/config/cast.gni")
   import("//build/config/clang/clang.gni")
   import("//build/config/dcheck_always_on.gni")
   import("//build/toolchain/siso.gni")
diff --git a/build/config/buildflags_paint_preview.gni b/build/config/buildflags_paint_preview.gni
index 951b6608..f5eabf4 100644
--- a/build/config/buildflags_paint_preview.gni
+++ b/build/config/buildflags_paint_preview.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/features.gni")
 
 declare_args() {
diff --git a/build/config/cast.gni b/build/config/cast.gni
new file mode 100644
index 0000000..c4fd6ac
--- /dev/null
+++ b/build/config/cast.gni
@@ -0,0 +1,122 @@
+# Copyright 2015 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# The args declared in this file should be referenced by components outside of
+# //chromecast. Args needed only in //chromecast should be declared in
+# //chromecast/chromecast.gni.
+declare_args() {
+  # Set this true for an audio-only Chromecast build.
+  # TODO(crbug.com/1293538): Replace with a buildflag for speaker-only builds not
+  # specific to Cast.
+  is_cast_audio_only = false
+
+  # If non empty, rpath of executables is set to this.
+  # If empty, default value is used.
+  target_rpath = ""
+
+  # Set true to enable modular_updater.
+  enable_modular_updater = false
+
+  # True to enable the cast audio renderer.
+  #
+  # TODO(crbug.com/1293520): Remove this buildflag.
+  enable_cast_audio_renderer = false
+
+  # Set this to true to build for Nest hardware running Linux (aka "CastOS").
+  # Set this to false to use the defaults for Linux.
+  is_castos = false
+
+  # Set this to true to build for Android-based Cast devices.
+  # Set this to false to use the defaults for Android.
+  is_cast_android = false
+}
+
+# Restrict is_castos and is_cast_android to only be set on the target toolchain.
+is_castos = is_castos && current_toolchain == default_toolchain
+is_cast_android = is_cast_android && current_toolchain == default_toolchain
+
+declare_args() {
+  # Set this true for a Chromecast build. Chromecast builds are supported on
+  # Linux, Android, ChromeOS, and Fuchsia.
+  enable_cast_receiver = false
+}
+
+declare_args() {
+  # True to enable the cast renderer.  It is enabled by default for Linux and
+  # Android audio only builds.
+  #
+  # TODO(crbug.com/1293520):  Remove this buildflag.
+  enable_cast_renderer =
+      enable_cast_receiver &&
+      (is_linux || is_chromeos || (is_cast_audio_only && is_android))
+}
+
+# Configures media options for cast.  See media/media_options.gni
+cast_mojo_media_services = []
+cast_mojo_media_host = ""
+
+if (enable_cast_audio_renderer) {
+  if (is_android) {
+    cast_mojo_media_services = [
+      "cdm",
+      "audio_decoder",
+    ]
+  }
+
+  if (!is_cast_audio_only) {
+    cast_mojo_media_services += [ "video_decoder" ]
+  }
+
+  if (is_android && is_cast_audio_only) {
+    cast_mojo_media_host = "browser"
+  } else {
+    cast_mojo_media_host = "gpu"
+  }
+} else if (enable_cast_renderer) {
+  # In this path, mojo media services are hosted in two processes:
+  # 1. "renderer" and "cdm" run in browser process. This is hard coded in the
+  # code.
+  # 2. "video_decoder" runs in the process specified by "cast_mojo_media_host".
+  cast_mojo_media_services = [
+    "cdm",
+    "renderer",
+  ]
+  if (!is_cast_audio_only) {
+    cast_mojo_media_services += [ "video_decoder" ]
+  }
+
+  cast_mojo_media_host = "gpu"
+} else if (is_android) {
+  # On Android, all the enabled mojo media services run in the process specified
+  # by "cast_mojo_media_host".
+  cast_mojo_media_services = [
+    "cdm",
+    "audio_decoder",
+  ]
+  if (!is_cast_audio_only) {
+    # These are Cast/Android devices with Video capabilities (and GPU)
+    cast_mojo_media_services += [ "video_decoder" ]
+    cast_mojo_media_host = "gpu"
+  } else {
+    # These are Cast/Android devices with only Audio capabilities (no GPU)
+    cast_mojo_media_host = "browser"
+  }
+}
+
+# Assert that Chromecast is being built for a supported platform.
+assert(is_linux || is_chromeos || is_android || is_fuchsia ||
+           !enable_cast_receiver,
+       "Cast receiver builds are not supported on $current_os")
+
+assert(enable_cast_receiver || !is_cast_audio_only,
+       "is_cast_audio_only = true requires enable_cast_receiver = true.")
+
+assert(enable_cast_receiver || !is_castos,
+       "is_castos = true requires enable_cast_receiver = true.")
+assert(is_linux || !is_castos, "is_castos = true requires is_linux = true.")
+
+assert(enable_cast_receiver || !is_cast_android,
+       "is_cast_android = true requires enable_cast_receiver = true.")
+assert(is_android || !is_cast_android,
+       "is_cast_android = true requires is_android = true.")
diff --git a/build/config/chromecast/BUILD.gn b/build/config/chromecast/BUILD.gn
index acaf990..97bbef72 100644
--- a/build/config/chromecast/BUILD.gn
+++ b/build/config/chromecast/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 
 assert(is_castos || is_cast_android)
 
diff --git a/build/config/chromecast_build.gni b/build/config/chromecast_build.gni
index e8294ce7..905241c 100644
--- a/build/config/chromecast_build.gni
+++ b/build/config/chromecast_build.gni
@@ -1,124 +1,11 @@
-# Copyright 2015 The Chromium Authors
+# Copyright 2023 The Chromium Authors
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# The args declared in this file should be referenced by components outside of
-# //chromecast. Args needed only in //chromecast should be declared in
-# //chromecast/chromecast.gni.
+# !!!                           DO NOT ADD NEW USAGES.                      !!!
+# !!! This file is deprecated and only exists for backwards compatility     !!!
+# !!! with third party repos that include it directly :(                    !!!
 #
-# TODO(crbug.com/1294964): Rename this file after is_chromecast is removed.
-declare_args() {
-  # Set this true for an audio-only Chromecast build.
-  # TODO(crbug.com/1293538): Replace with a buildflag for speaker-only builds not
-  # specific to Cast.
-  is_cast_audio_only = false
+# TODO(crbug.com/1294964): Update those usages and remove this file.
 
-  # If non empty, rpath of executables is set to this.
-  # If empty, default value is used.
-  target_rpath = ""
-
-  # Set true to enable modular_updater.
-  enable_modular_updater = false
-
-  # True to enable the cast audio renderer.
-  #
-  # TODO(crbug.com/1293520): Remove this buildflag.
-  enable_cast_audio_renderer = false
-
-  # Set this to true to build for Nest hardware running Linux (aka "CastOS").
-  # Set this to false to use the defaults for Linux.
-  is_castos = false
-
-  # Set this to true to build for Android-based Cast devices.
-  # Set this to false to use the defaults for Android.
-  is_cast_android = false
-}
-
-# Restrict is_castos and is_cast_android to only be set on the target toolchain.
-is_castos = is_castos && current_toolchain == default_toolchain
-is_cast_android = is_cast_android && current_toolchain == default_toolchain
-
-declare_args() {
-  # Set this true for a Chromecast build. Chromecast builds are supported on
-  # Linux, Android, ChromeOS, and Fuchsia.
-  enable_cast_receiver = false
-}
-
-declare_args() {
-  # True to enable the cast renderer.  It is enabled by default for Linux and
-  # Android audio only builds.
-  #
-  # TODO(crbug.com/1293520):  Remove this buildflag.
-  enable_cast_renderer =
-      enable_cast_receiver &&
-      (is_linux || is_chromeos || (is_cast_audio_only && is_android))
-}
-
-# Configures media options for cast.  See media/media_options.gni
-cast_mojo_media_services = []
-cast_mojo_media_host = ""
-
-if (enable_cast_audio_renderer) {
-  if (is_android) {
-    cast_mojo_media_services = [
-      "cdm",
-      "audio_decoder",
-    ]
-  }
-
-  if (!is_cast_audio_only) {
-    cast_mojo_media_services += [ "video_decoder" ]
-  }
-
-  if (is_android && is_cast_audio_only) {
-    cast_mojo_media_host = "browser"
-  } else {
-    cast_mojo_media_host = "gpu"
-  }
-} else if (enable_cast_renderer) {
-  # In this path, mojo media services are hosted in two processes:
-  # 1. "renderer" and "cdm" run in browser process. This is hard coded in the
-  # code.
-  # 2. "video_decoder" runs in the process specified by "cast_mojo_media_host".
-  cast_mojo_media_services = [
-    "cdm",
-    "renderer",
-  ]
-  if (!is_cast_audio_only) {
-    cast_mojo_media_services += [ "video_decoder" ]
-  }
-
-  cast_mojo_media_host = "gpu"
-} else if (is_android) {
-  # On Android, all the enabled mojo media services run in the process specified
-  # by "cast_mojo_media_host".
-  cast_mojo_media_services = [
-    "cdm",
-    "audio_decoder",
-  ]
-  if (!is_cast_audio_only) {
-    # These are Cast/Android devices with Video capabilities (and GPU)
-    cast_mojo_media_services += [ "video_decoder" ]
-    cast_mojo_media_host = "gpu"
-  } else {
-    # These are Cast/Android devices with only Audio capabilities (no GPU)
-    cast_mojo_media_host = "browser"
-  }
-}
-
-# Assert that Chromecast is being built for a supported platform.
-assert(is_linux || is_chromeos || is_android || is_fuchsia ||
-           !enable_cast_receiver,
-       "Cast receiver builds are not supported on $current_os")
-
-assert(enable_cast_receiver || !is_cast_audio_only,
-       "is_cast_audio_only = true requires enable_cast_receiver = true.")
-
-assert(enable_cast_receiver || !is_castos,
-       "is_castos = true requires enable_cast_receiver = true.")
-assert(is_linux || !is_castos, "is_castos = true requires is_linux = true.")
-
-assert(enable_cast_receiver || !is_cast_android,
-       "is_cast_android = true requires enable_cast_receiver = true.")
-assert(is_android || !is_cast_android,
-       "is_cast_android = true requires is_android = true.")
+import("//build/config/cast.gni")
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index b1d92979..636652d 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -3,8 +3,8 @@
 # found in the LICENSE file.
 
 import("//build/config/c++/c++.gni")
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/chromeos/args.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/compiler/pgo/pgo.gni")
diff --git a/build/config/compiler/pgo/pgo.gni b/build/config/compiler/pgo/pgo.gni
index 9e50afb..a85334d8 100644
--- a/build/config/compiler/pgo/pgo.gni
+++ b/build/config/compiler/pgo/pgo.gni
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/dcheck_always_on.gni")
 import("//build/config/features.gni")
diff --git a/build/config/features.gni b/build/config/features.gni
index 7676483..a142b45 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -14,8 +14,8 @@
 # There is more advice on where to put build flags in the "Build flag" section
 # of //build/config/BUILDCONFIG.gn.
 
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 
 declare_args() {
   # Enables proprietary codecs and demuxers; e.g. H264, AAC, MP3, and MP4.
diff --git a/build/config/fuchsia/BUILD.gn b/build/config/fuchsia/BUILD.gn
index 3702eec..43133d5 100644
--- a/build/config/fuchsia/BUILD.gn
+++ b/build/config/fuchsia/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/clang/clang.gni")
 import("//build/config/fuchsia/generate_runner_scripts.gni")
 import("//build/config/fuchsia/gn_configs.gni")
diff --git a/build/config/fuchsia/generate_runner_scripts.gni b/build/config/fuchsia/generate_runner_scripts.gni
index 747fb67..6fba7f4 100644
--- a/build/config/fuchsia/generate_runner_scripts.gni
+++ b/build/config/fuchsia/generate_runner_scripts.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/fuchsia/config.gni")
 import("//build/config/fuchsia/fuchsia_package_metadata.gni")
 import("//build/config/gclient_args.gni")
diff --git a/build/config/linux/libdrm/BUILD.gn b/build/config/linux/libdrm/BUILD.gn
index 31ab0d8..a37bd24c 100644
--- a/build/config/linux/libdrm/BUILD.gn
+++ b/build/config/linux/libdrm/BUILD.gn
@@ -1,7 +1,7 @@
 # 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.
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/args.gni")
 import("//build/config/linux/pkg_config.gni")
 
diff --git a/build/config/ozone.gni b/build/config/ozone.gni
index e85db6b..8a3bc28c 100644
--- a/build/config/ozone.gni
+++ b/build/config/ozone.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/toolchain/toolchain.gni")
 
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn
index c112ba4f..19d2685 100644
--- a/build/config/sanitizers/BUILD.gn
+++ b/build/config/sanitizers/BUILD.gn
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/clang/clang.gni")
 import("//build/config/rust.gni")
 import("//build/config/sanitizers/sanitizers.gni")
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni
index fb382ee8..928c9a4 100644
--- a/build/config/sanitizers/sanitizers.gni
+++ b/build/config/sanitizers/sanitizers.gni
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/chromeos/args.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/profiling/profiling.gni")
diff --git a/build/config/ui.gni b/build/config/ui.gni
index b560f37..1ad21d7 100644
--- a/build/config/ui.gni
+++ b/build/config/ui.gni
@@ -17,7 +17,7 @@
 # There is more advice on where to put build flags in the "Build flag" section
 # of //build/config/BUILDCONFIG.gn.
 
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/args.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/ozone.gni")
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni
index 9170959..23ec903 100644
--- a/build/toolchain/toolchain.gni
+++ b/build/toolchain/toolchain.gni
@@ -5,8 +5,8 @@
 # Toolchain-related configuration that may be needed outside the context of the
 # toolchain() rules themselves.
 
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build_overrides/build.gni")
 
 declare_args() {
diff --git a/build_overrides/build.gni b/build_overrides/build.gni
index 7370151f..9187225 100644
--- a/build_overrides/build.gni
+++ b/build_overrides/build.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/features.gni")
 import("//build/config/gclient_args.gni")
 
diff --git a/build_overrides/partition_alloc.gni b/build_overrides/partition_alloc.gni
index a6306a0..76cd587f 100644
--- a/build_overrides/partition_alloc.gni
+++ b/build_overrides/partition_alloc.gni
@@ -24,7 +24,7 @@
 #
 # {variable}_default works as the default value of {variable}.
 
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 if (is_ios) {
   import("//build/config/ios/ios_sdk.gni")
diff --git a/chrome/VERSION b/chrome/VERSION
index 6653cf05..1be427f 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=121
 MINOR=0
-BUILD=6112
+BUILD=6113
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 04b7532..7fbd5683 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1301,7 +1301,6 @@
       "javatests/src/org/chromium/chrome/browser/FederatedIdentityTestUtils.java",
       "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTestRule.java",
       "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java",
-      "javatests/src/org/chromium/chrome/browser/directactions/FakeDirectActionReporter.java",
       "javatests/src/org/chromium/chrome/browser/modaldialog/ChromeModalDialogTestUtils.java",
       "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java",
       "javatests/src/org/chromium/chrome/browser/webapps/TestFetchStorageCallback.java",
@@ -1610,6 +1609,8 @@
       "//chrome/browser/fullscreen/android:java",
       "//chrome/browser/gsa:java",
       "//chrome/browser/history_clusters:java",
+      "//chrome/browser/hub:factory_java",
+      "//chrome/browser/hub:java",
       "//chrome/browser/image_descriptions:javatests",
       "//chrome/browser/incognito:incognito_java_tests",
       "//chrome/browser/incognito:java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index b73655f..5783ed6e 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -553,17 +553,6 @@
   "java/src/org/chromium/chrome/browser/device_dialog/UsbChooserDialog.java",
   "java/src/org/chromium/chrome/browser/device_lock/DeviceLockActivity.java",
   "java/src/org/chromium/chrome/browser/device_lock/DeviceLockActivityLauncherImpl.java",
-  "java/src/org/chromium/chrome/browser/directactions/ChromeDirectActionIds.java",
-  "java/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandler.java",
-  "java/src/org/chromium/chrome/browser/directactions/DirectActionCoordinator.java",
-  "java/src/org/chromium/chrome/browser/directactions/DirectActionHandler.java",
-  "java/src/org/chromium/chrome/browser/directactions/DirectActionInitializer.java",
-  "java/src/org/chromium/chrome/browser/directactions/DirectActionReporter.java",
-  "java/src/org/chromium/chrome/browser/directactions/DirectActionUsageHistogram.java",
-  "java/src/org/chromium/chrome/browser/directactions/FindInPageDirectActionHandler.java",
-  "java/src/org/chromium/chrome/browser/directactions/GoBackDirectActionHandler.java",
-  "java/src/org/chromium/chrome/browser/directactions/MenuDirectActionHandler.java",
-  "java/src/org/chromium/chrome/browser/directactions/SimpleDirectActionHandler.java",
   "java/src/org/chromium/chrome/browser/display_cutout/ActivityDisplayCutoutModeSupplier.java",
   "java/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTabHelper.java",
   "java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index e59bcfac..fa07d55 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -185,8 +185,6 @@
   "junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java",
   "junit/src/org/chromium/chrome/browser/customtabs/shadows/ShadowExternalNavigationDelegateImpl.java",
   "junit/src/org/chromium/chrome/browser/desktop_site/DesktopSiteSettingsIPHControllerUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/directactions/FindInPageDirectActionHandlerTest.java",
-  "junit/src/org/chromium/chrome/browser/directactions/GoBackDirectActionHandlerTest.java",
   "junit/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutControllerTest.java",
   "junit/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerTest.java",
   "junit/src/org/chromium/chrome/browser/dom_distiller/ReaderModeToolbarButtonControllerTest.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index d30c2cc7..8b8cd22 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -10,6 +10,7 @@
 
 chrome_test_java_sources = [
   "java/src/org/chromium/chrome/browser/app/feed/NavigationRecorderTest.java",
+  "java/src/org/chromium/chrome/browser/hub/HubLayoutPublicTransitTest.java",
   "javatests/src/org/chromium/chrome/browser/ActivityTabProviderTest.java",
   "javatests/src/org/chromium/chrome/browser/ChromeActionModeHandlerTest.java",
   "javatests/src/org/chromium/chrome/browser/ChromeTabbedActivityTest.java",
@@ -170,14 +171,6 @@
   "javatests/src/org/chromium/chrome/browser/device_dialog/UsbChooserDialogTest.java",
   "javatests/src/org/chromium/chrome/browser/device_lock/DeviceLockActivityLauncherImplTest.java",
   "javatests/src/org/chromium/chrome/browser/device_lock/DeviceLockActivityTest.java",
-  "javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java",
-  "javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityCustomTabTest.java",
-  "javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityTabbedTest.java",
-  "javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityWebappTest.java",
-  "javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestRule.java",
-  "javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestUtils.java",
-  "javatests/src/org/chromium/chrome/browser/directactions/DirectActionsInActivityTest.java",
-  "javatests/src/org/chromium/chrome/browser/directactions/MenuDirectActionHandlerTest.java",
   "javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTest.java",
   "javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTestRule.java",
   "javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java",
diff --git a/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_sheet_tab_option_toggle.xml b/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_sheet_tab_option_toggle.xml
index 5cefd32..9d1713c 100644
--- a/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_sheet_tab_option_toggle.xml
+++ b/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_sheet_tab_option_toggle.xml
@@ -39,7 +39,7 @@
             android:textAppearance="@style/TextAppearance.TextMedium.Secondary" />
     </LinearLayout>
 
-    <com.google.android.material.switchmaterial.SwitchMaterial
+    <com.google.android.material.materialswitch.MaterialSwitch
         android:id="@+id/option_toggle_switch"
         android:layout_marginStart="16dp"
         android:layout_width="48dp"
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
index cf0481e79..175f85c7 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
@@ -552,13 +552,8 @@
 
     private void registerLayoutChangeListener() {
         if (mListLayoutListener != null) {
-            assert !mLayoutListenerRegistered
-                    || !ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mContext);
-
-            // TODO(crbug/1478720): Early out if already registered. This is possible as this may
-            // be called repeatedly when Start Surface Refactor is disabled, and the transition
-            // animation to the Tab Switcher is skipped. Remove this if check once Start Surface
-            // Refactor is enabled everywhere.
+            // TODO(crbug/1500016): There might be a timing or race condition that LayoutListener
+            // has been registered while it shouldn't be with Start surface refactor is enabled.
             if (mLayoutListenerRegistered) return;
 
             mLayoutListenerRegistered = true;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java
index 63dbecd..e1d8967 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardViewModel.java
@@ -76,8 +76,6 @@
     private static String getTitleText(
             Context context, @TabSuggestion.TabSuggestionAction int suggestionActionType) {
         switch (suggestionActionType) {
-            case TabSuggestion.TabSuggestionAction.GROUP:
-                return "";
             case TabSuggestion.TabSuggestionAction.CLOSE:
                 return context.getString(R.string.tab_cleanup_message_card_title);
             default:
@@ -91,8 +89,6 @@
         int suggestionActionType = data.getActionType();
 
         switch (suggestionActionType) {
-            case TabSuggestion.TabSuggestionAction.GROUP:
-                return "";
             case TabSuggestion.TabSuggestionAction.CLOSE:
                 return context.getResources()
                         .getQuantityString(
@@ -108,8 +104,6 @@
     private static String getActionText(
             Context context, @TabSuggestion.TabSuggestionAction int suggestionActionType) {
         switch (suggestionActionType) {
-            case TabSuggestion.TabSuggestionAction.GROUP:
-                return "";
             case TabSuggestion.TabSuggestionAction.CLOSE:
                 return context.getString(R.string.tab_cleanup_message_card_review_tabs_button);
             default:
@@ -121,8 +115,6 @@
     private static String getSecondaryActionText(
             Context context, @TabSuggestion.TabSuggestionAction int suggestionActionType) {
         switch (suggestionActionType) {
-            case TabSuggestion.TabSuggestionAction.GROUP:
-                return "";
             case TabSuggestion.TabSuggestionAction.CLOSE:
                 return context.getString(R.string.tab_cleanup_message_card_close_tabs_button);
             default:
@@ -134,8 +126,6 @@
     private static int getIconWidth(
             Context context, @TabSuggestion.TabSuggestionAction int suggestionActionType) {
         switch (suggestionActionType) {
-            case TabSuggestion.TabSuggestionAction.GROUP:
-                return 0;
             case TabSuggestion.TabSuggestionAction.CLOSE:
                 return (int)
                         context.getResources()
@@ -149,8 +139,6 @@
     private static int getIconHeight(
             Context context, @TabSuggestion.TabSuggestionAction int suggestionActionType) {
         switch (suggestionActionType) {
-            case TabSuggestion.TabSuggestionAction.GROUP:
-                return 0;
             case TabSuggestion.TabSuggestionAction.CLOSE:
                 return (int)
                         context.getResources()
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageService.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageService.java
index bc9c639..95abef1 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageService.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageService.java
@@ -147,12 +147,6 @@
                         TabSelectionEditorAction.ButtonType.TEXT,
                         TabSelectionEditorAction.IconPosition.END);
                 break;
-            case TabSuggestion.TabSuggestionAction.GROUP:
-                action = TabSelectionEditorGroupAction.createAction(mContext,
-                        TabSelectionEditorAction.ShowMode.IF_ROOM,
-                        TabSelectionEditorAction.ButtonType.TEXT,
-                        TabSelectionEditorAction.IconPosition.END);
-                break;
             default:
                 assert false;
                 return null;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestion.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestion.java
index 5262ab1..33ddea66 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestion.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestion.java
@@ -16,11 +16,10 @@
  */
 public final class TabSuggestion {
     /** Types of Suggestion Actions */
-    @IntDef({TabSuggestion.TabSuggestionAction.GROUP, TabSuggestion.TabSuggestionAction.CLOSE})
+    @IntDef({TabSuggestion.TabSuggestionAction.CLOSE})
     @Retention(RetentionPolicy.SOURCE)
     public @interface TabSuggestionAction {
-        int GROUP = 0;
-        int CLOSE = 1;
+        int CLOSE = 0;
     }
 
     private final List<TabContext.TabInfo> mTabsInfo;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java
index 22a62a7b..e8f0d2e 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java
@@ -97,11 +97,6 @@
                         aggregated.add(tabSuggestion);
                     }
                     break;
-                case TabSuggestion.TabSuggestionAction.GROUP:
-                    if (!tabSuggestion.getTabsInfo().isEmpty()) {
-                        aggregated.add(tabSuggestion);
-                    }
-                    break;
                 default:
                     android.util.Log.e(
                             TAG, String.format("Unknown action: %d", tabSuggestion.getAction()));
@@ -240,9 +235,6 @@
             case TabSuggestionAction.CLOSE:
                 suffix = "Closing";
                 break;
-            case TabSuggestionAction.GROUP:
-                suffix = "Grouping";
-                break;
             default:
                 assert false : "Unknown TabSuggestion action";
         }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherTabletTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherTabletTest.java
index 42e02bf..d72feab 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherTabletTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherTabletTest.java
@@ -90,7 +90,7 @@
     "force-fieldtrials=Study/Group"
 })
 @EnableFeatures({ChromeFeatureList.TAB_STRIP_REDESIGN, ChromeFeatureList.EMPTY_STATES})
-@DisableFeatures(ChromeFeatureList.TAB_TO_GTS_ANIMATION)
+@DisableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION, ChromeFeatureList.START_SURFACE_REFACTOR})
 @Restriction({
     Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE,
     UiRestriction.RESTRICTION_TYPE_TABLET
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
index 55dadb8..7d434465 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
@@ -129,8 +129,6 @@
     public void getMessageItemsTest_OneMessageForEachMessageType() {
         enqueueMessageItem(
                 MessageService.MessageType.TAB_SUGGESTION, TabSuggestion.TabSuggestionAction.CLOSE);
-        enqueueMessageItem(
-                MessageService.MessageType.TAB_SUGGESTION, TabSuggestion.TabSuggestionAction.GROUP);
         enqueueMessageItem(MessageService.MessageType.FOR_TESTING, TESTING_ACTION);
 
         List<MessageCardProviderMediator.Message> messages = mMediator.getMessageItems();
@@ -349,22 +347,6 @@
     }
 
     @Test
-    public void buildModel_ForGroupingTabSuggestion() {
-        enqueueMessageItem(
-                MessageService.MessageType.TAB_SUGGESTION, TabSuggestion.TabSuggestionAction.GROUP);
-
-        PropertyModel model =
-                mMediator
-                        .getReadyMessageItemsForTesting()
-                        .get(MessageService.MessageType.TAB_SUGGESTION)
-                        .get(0)
-                        .model;
-        Assert.assertEquals(
-                MessageService.MessageType.TAB_SUGGESTION,
-                model.get(MessageCardViewProperties.MESSAGE_TYPE));
-    }
-
-    @Test
     public void buildModel_ForPriceMessage() {
         String titleText = "Price drop spotted";
         doReturn(titleText).when(mContext).getString(R.string.price_drop_spotted_title);
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageServiceUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageServiceUnitTest.java
index 6847c76..23d78660 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageServiceUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageServiceUnitTest.java
@@ -206,61 +206,6 @@
         assertEquals(DISMISSED, capturedFeedback.tabSuggestionResponse);
     }
 
-    // Tests for grouping suggestion
-    @Test
-    public void testReviewHandler_groupSuggestion() {
-        TabSuggestion tabSuggestion =
-                prepareTabSuggestion(
-                        Arrays.asList(mTab1, mTab2), TabSuggestion.TabSuggestionAction.GROUP);
-
-        mMessageService.review(tabSuggestion, mTabSuggestionFeedbackCallback);
-        verify(mTabSelectionEditorController).configureToolbarWithMenuItems(any(), any());
-        verify(mTabSelectionEditorController)
-                .show(eq(Arrays.asList(mTab1, mTab2, mTab3)), eq(2), eq(null));
-
-        tabSuggestion =
-                prepareTabSuggestion(
-                        Arrays.asList(mTab1, mTab3), TabSuggestion.TabSuggestionAction.GROUP);
-        mMessageService.review(tabSuggestion, mTabSuggestionFeedbackCallback);
-        verify(mTabSelectionEditorController)
-                .show(eq(Arrays.asList(mTab1, mTab3, mTab2)), eq(2), eq(null));
-    }
-
-    @Test
-    public void testGroupingSuggestionActionHandler() {
-        List<Tab> suggestedTabs = Arrays.asList(mTab1, mTab2);
-        List<Integer> suggestedTabIds = Arrays.asList(TAB1_ID, TAB2_ID);
-        TabSuggestion tabSuggestion =
-                prepareTabSuggestion(suggestedTabs, TabSuggestion.TabSuggestionAction.GROUP);
-
-        assertEquals(3, mTabModelSelector.getCurrentModel().getCount());
-
-        LinkedHashSet<Integer> tabSet = new LinkedHashSet<>();
-        tabSet.add(TAB1_ID);
-        tabSet.add(TAB2_ID);
-        doReturn(tabSet).when(mSelectionDelegate).getSelectedItems();
-        TabSelectionEditorAction action =
-                mMessageService.getAction(tabSuggestion, mTabSuggestionFeedbackCallback);
-        action.configure(
-                mTabModelSelector,
-                mSelectionDelegate,
-                mActionDelegate,
-                /* editorSupportsActionOnRelatedTabs= */ false);
-        action.perform();
-
-        verify(mTabSuggestionFeedbackCallback)
-                .onResult(mTabSuggestionFeedbackCallbackArgumentCaptor.capture());
-        verify(mTabGroupModelFilter)
-                .mergeListOfTabsToGroup(eq(suggestedTabs), eq(mTab2), eq(true), eq(true));
-
-        TabSuggestionFeedback capturedFeedback =
-                mTabSuggestionFeedbackCallbackArgumentCaptor.getValue();
-        assertEquals(tabSuggestion, capturedFeedback.tabSuggestion);
-        assertEquals(ACCEPTED, capturedFeedback.tabSuggestionResponse);
-        assertEquals(suggestedTabIds, capturedFeedback.selectedTabIds);
-        assertEquals(3, capturedFeedback.totalTabCount);
-    }
-
     @Test
     public void testDismiss() {
         List<Tab> suggestedTabs = Arrays.asList(mTab1, mTab2);
@@ -301,14 +246,10 @@
         TabSuggestion tabSuggestion2 =
                 prepareTabSuggestion(
                         Arrays.asList(mTab1, mTab2), TabSuggestion.TabSuggestionAction.CLOSE);
-        TabSuggestion tabSuggestion3 =
-                prepareTabSuggestion(
-                        Arrays.asList(mTab1, mTab2), TabSuggestion.TabSuggestionAction.GROUP);
 
         mMessageService.onNewSuggestion(
-                Arrays.asList(tabSuggestion, tabSuggestion2, tabSuggestion3),
-                mTabSuggestionFeedbackCallback);
-        inOrder.verify(mMessageObserver, times(3))
+                Arrays.asList(tabSuggestion, tabSuggestion2), mTabSuggestionFeedbackCallback);
+        inOrder.verify(mMessageObserver, times(2))
                 .messageReady(
                         eq(MessageService.MessageType.TAB_SUGGESTION),
                         any(TabSuggestionMessageService.TabSuggestionMessageData.class));
diff --git a/chrome/android/java/res/layout/bookmark_save_flow.xml b/chrome/android/java/res/layout/bookmark_save_flow.xml
index b1265b7..4a348e3e 100644
--- a/chrome/android/java/res/layout/bookmark_save_flow.xml
+++ b/chrome/android/java/res/layout/bookmark_save_flow.xml
@@ -127,7 +127,7 @@
                 android:textAppearance="@style/TextAppearance.TextSmall.Secondary" />
         </LinearLayout>
 
-        <androidx.appcompat.widget.SwitchCompat
+        <com.google.android.material.materialswitch.MaterialSwitch
             android:id="@+id/notification_switch"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
diff --git a/chrome/android/java/res/layout/improved_bookmark_save_flow.xml b/chrome/android/java/res/layout/improved_bookmark_save_flow.xml
index 485eec8..9b8e6020 100644
--- a/chrome/android/java/res/layout/improved_bookmark_save_flow.xml
+++ b/chrome/android/java/res/layout/improved_bookmark_save_flow.xml
@@ -139,7 +139,7 @@
             android:textAppearance="@style/TextAppearance.TextSmall.Secondary" />
       </LinearLayout>
 
-      <androidx.appcompat.widget.SwitchCompat
+      <com.google.android.material.materialswitch.MaterialSwitch
           android:id="@+id/price_tracking_switch"
           app:layout_constraintTop_toTopOf="parent"
           app:layout_constraintBottom_toBottomOf="parent"
diff --git a/chrome/android/java/res/layout/incognito_cookie_controls_card.xml b/chrome/android/java/res/layout/incognito_cookie_controls_card.xml
index 8fa2616..9efaf7f 100644
--- a/chrome/android/java/res/layout/incognito_cookie_controls_card.xml
+++ b/chrome/android/java/res/layout/incognito_cookie_controls_card.xml
@@ -26,14 +26,14 @@
         android:layout_alignParentStart="true"
         app:tint="@color/default_icon_color_light" />
 
-    <com.google.android.material.switchmaterial.SwitchMaterial
+    <com.google.android.material.materialswitch.MaterialSwitch
         android:id="@+id/cookie_controls_card_toggle"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_centerVertical="true"
-        android:theme="@style/SwitchMaterialDark"
         android:layout_alignParentEnd="true"
         android:contentDescription="@string/new_tab_otr_third_party_cookie"
+        style="@style/Widget.BrowserUI.Switch.Incognito"
         app:showText="false" />
 
     <org.chromium.ui.widget.TextViewWithLeading
diff --git a/chrome/android/java/res/layout/revamped_incognito_cookie_controls_card.xml b/chrome/android/java/res/layout/revamped_incognito_cookie_controls_card.xml
index 0099803..55fdd14 100644
--- a/chrome/android/java/res/layout/revamped_incognito_cookie_controls_card.xml
+++ b/chrome/android/java/res/layout/revamped_incognito_cookie_controls_card.xml
@@ -26,14 +26,14 @@
         android:layout_alignParentStart="true"
         app:tint="@color/default_icon_color_light" />
 
-    <com.google.android.material.switchmaterial.SwitchMaterial
+    <com.google.android.material.materialswitch.MaterialSwitch
         android:id="@+id/revamped_cookie_controls_card_toggle"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_centerVertical="true"
-        android:theme="@style/SwitchMaterialDark"
         android:layout_alignParentEnd="true"
         android:contentDescription="@string/revamped_incognito_ntp_otr_third_party_cookie"
+        style="@style/Widget.BrowserUI.Switch.Incognito"
         app:showText="false" />
 
     <org.chromium.ui.widget.TextViewWithLeading
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
index 8801e00..4818f9d5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
@@ -13,7 +13,6 @@
 import org.chromium.base.PackageUtils;
 import org.chromium.base.ResettersForTesting;
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
-import org.chromium.chrome.browser.directactions.DirectActionCoordinator;
 import org.chromium.chrome.browser.gsa.GSAHelper;
 import org.chromium.chrome.browser.historyreport.AppIndexingReporter;
 import org.chromium.chrome.browser.init.ChromeStartupDelegate;
@@ -99,13 +98,6 @@
     }
 
     /**
-     * Returns a new {@link DirectActionCoordinator} instance, if available.
-     */
-    public @Nullable DirectActionCoordinator createDirectActionCoordinator() {
-        return null;
-    }
-
-    /**
      * @return An instance of GoogleActivityController.
      */
     public GoogleActivityController createGoogleActivityController() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 4b3c279..fbd86de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -51,6 +51,7 @@
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
+import org.chromium.base.supplier.LazyOneshotSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.OneShotCallback;
 import org.chromium.base.supplier.OneshotSupplier;
@@ -104,6 +105,10 @@
 import org.chromium.chrome.browser.fonts.FontPreloader;
 import org.chromium.chrome.browser.gesturenav.NavigationSheet;
 import org.chromium.chrome.browser.homepage.HomepageManager;
+import org.chromium.chrome.browser.hub.DefaultPaneOrderController;
+import org.chromium.chrome.browser.hub.HubFieldTrial;
+import org.chromium.chrome.browser.hub.HubLayoutDependencyHolder;
+import org.chromium.chrome.browser.hub.HubProvider;
 import org.chromium.chrome.browser.incognito.IncognitoNotificationManager;
 import org.chromium.chrome.browser.incognito.IncognitoNotificationPresenceController;
 import org.chromium.chrome.browser.incognito.IncognitoProfileDestroyer;
@@ -379,6 +384,7 @@
             new OneshotSupplierImpl<>();
     private ObservableSupplierImpl<Tab> mStartSurfaceParentTabSupplier =
             new ObservableSupplierImpl<>();
+    private HubProvider mHubProvider;
     private ObservableSupplierImpl<TabModelStartupInfo> mTabModelStartupInfoSupplier;
     // Calls isStartSurfaceRefactorEnabled() instead of using this variable directly.
     private Boolean mIsStartSurfaceRefactorEnabled;
@@ -668,6 +674,28 @@
         }
     }
 
+    private HubLayoutDependencyHolder createHubLayoutDependencyHolder() {
+        if (!HubFieldTrial.isHubEnabled()) return null;
+
+        // The tab_switcher_view_holder can be used on both tablet and phone because Hub's
+        // animations don't depend on the compositor. This differs from the current tab switcher
+        // behavior on phones.
+        LazyOneshotSupplier<ViewGroup> rootViewSupplier =
+                LazyOneshotSupplier.fromSupplier(
+                        () -> {
+                            ViewStub stub =
+                                    (ViewStub) findViewById(R.id.tab_switcher_view_holder_stub);
+                            return (ViewGroup) stub.inflate();
+                        });
+
+        return new HubLayoutDependencyHolder(
+                mHubProvider.getHubManagerSupplier(),
+                rootViewSupplier,
+                mRootUiCoordinator.getScrimCoordinator(),
+                rootViewSupplier::get,
+                mTabModelSelector::isIncognitoSelected);
+    }
+
     private void setupCompositorContentPreNativeForPhone() {
         if (isTablet()) return;
 
@@ -679,13 +707,20 @@
             // We should inline createStartSurface() (if enabled) once the refactor is launched.
             createTabSwitcherOrStartSurface(compositorViewHolder, compositorViewHolder);
 
-            mLayoutManager = new LayoutManagerChromePhone(compositorViewHolder, mContentContainer,
-                mStartSurfaceSupplier, mTabSwitcherSupplier, getBrowserControlsManager(),
-                getTabContentManagerSupplier(), mRootUiCoordinator::getTopUiThemeColorProvider,
-                () -> {
-                    createGridTabSwitcher(compositorViewHolder, compositorViewHolder);
-                    return compositorViewHolder;
-                });
+            mLayoutManager =
+                    new LayoutManagerChromePhone(
+                            compositorViewHolder,
+                            mContentContainer,
+                            mStartSurfaceSupplier,
+                            mTabSwitcherSupplier,
+                            getBrowserControlsManager(),
+                            getTabContentManagerSupplier(),
+                            mRootUiCoordinator::getTopUiThemeColorProvider,
+                            () -> {
+                                createGridTabSwitcher(compositorViewHolder, compositorViewHolder);
+                                return compositorViewHolder;
+                            },
+                            createHubLayoutDependencyHolder());
             mLayoutStateProviderSupplier.set(mLayoutManager);
         }
     }
@@ -718,6 +753,7 @@
                             mRootUiCoordinator.getScrimCoordinator(),
                             getLifecycleDispatcher(),
                             () -> createAndSetStartSurfaceForTablet(),
+                            createHubLayoutDependencyHolder(),
                             mMultiInstanceManager,
                             mDragDropDelegate,
                             toolbarContainerView,
@@ -1799,6 +1835,9 @@
         if (DseNewTabUrlManager.isNewTabSearchEngineUrlAndroidEnabled()) {
             mDseNewTabUrlManager = new DseNewTabUrlManager(mTabModelProfileSupplier);
         }
+        if (HubFieldTrial.isHubEnabled()) {
+            mHubProvider = new HubProvider(this, new DefaultPaneOrderController());
+        }
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
index 73ef797..1f9e203e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -18,7 +18,6 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.CancellationSignal;
 import android.os.SystemClock;
 import android.util.Pair;
 import android.util.TypedValue;
@@ -57,7 +56,6 @@
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.base.supplier.UnownedUserDataSupplier;
-import org.chromium.build.annotations.UsedByReflection;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.ActivityUtils;
@@ -247,7 +245,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.function.Consumer;
 
 /**
  * A {@link AsyncInitializationActivity} that builds and manages a {@link CompositorViewHolder}
@@ -1513,26 +1510,6 @@
         }
     }
 
-    // TODO(crbug.com/973781): Once Chromium is built against Android Q SDK, replace
-    // @SuppressWarnings with @Override
-    @SuppressWarnings("MissingOverride")
-    @RequiresApi(29)
-    @UsedByReflection("Called from Android Q")
-    public void onPerformDirectAction(String actionId, Bundle arguments,
-            CancellationSignal cancellationSignal, Consumer<Bundle> callback) {
-        mRootUiCoordinator.onPerformDirectAction(actionId, arguments, cancellationSignal, callback);
-    }
-
-    // TODO(crbug.com/973781): Once Chromium is built against Android Q SDK:
-    //  - replace @SuppressWarnings with @Override
-    //  - replace Consumer with Consumer<List<DirectAction>>
-    @SuppressWarnings("MissingOverride")
-    @RequiresApi(29)
-    @UsedByReflection("Called from Android Q")
-    public void onGetDirectActions(CancellationSignal cancellationSignal, Consumer callback) {
-        mRootUiCoordinator.onGetDirectActions(cancellationSignal, callback);
-    }
-
     @Override
     public long getOnCreateTimestampMs() {
         return super.getOnCreateTimestampMs();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java
index 23c365d76..93c4204 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java
@@ -158,7 +158,7 @@
 
         mIsCreatingFolder = getIntent().getBooleanExtra(INTENT_IS_CREATING_FOLDER, false);
         if (mIsCreatingFolder) {
-            mParentId = mModel.getMobileFolderId();
+            mParentId = mModel.getDefaultFolder();
         } else {
             mParentId = mModel.getBookmarkById(mBookmarksToMove.get(0)).getParentId();
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
index 236de7c..17327bd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -22,6 +22,9 @@
 import org.chromium.chrome.browser.device.DeviceClassManager;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
+import org.chromium.chrome.browser.hub.HubFieldTrial;
+import org.chromium.chrome.browser.hub.HubLayout;
+import org.chromium.chrome.browser.hub.HubLayoutDependencyHolder;
 import org.chromium.chrome.browser.layouts.LayoutType;
 import org.chromium.chrome.browser.layouts.components.VirtualView;
 import org.chromium.chrome.browser.tab.Tab;
@@ -74,6 +77,12 @@
      */
     protected Layout mTabSwitcherLayout;
 
+    /**
+     * A {@link Layout} that should be used when the user is in the tab switcher when the refactor
+     * flag and hub flags are enabled.
+     */
+    protected Layout mHubLayout;
+
     // Event Filter Handlers
     private final SwipeHandler mToolbarSwipeHandler;
 
@@ -91,106 +100,142 @@
     private final ScrimCoordinator mScrimCoordinator;
     private final Callable<ViewGroup> mCreateTabSwitcherOrStartSurfaceCallable;
 
+    private final HubLayoutDependencyHolder mHubLayoutDependencyHolder;
+
     // Theme Color
     private TopUiThemeColorProvider mTopUiThemeColorProvider;
     private ThemeColorObserver mThemeColorObserver;
 
     /**
      * Creates the {@link LayoutManagerChrome} instance.
-     * @param host         A {@link LayoutManagerHost} instance.
+     *
+     * @param host A {@link LayoutManagerHost} instance.
      * @param contentContainer A {@link ViewGroup} for Android views to be bound to.
      * @param startSurfaceSupplier Supplier for an interface to talk to the Grid Tab Switcher.
-     *         Creates overviewLayout with this surface if this is has value. If not, {@link
-     *         #showLayout(int, boolean)} will create overviewLayout.
+     *     Creates overviewLayout with this surface if this is has value. If not, {@link
+     *     #showLayout(int, boolean)} will create overviewLayout.
      * @param tabSwitcherSupplier Supplier for an interface to talk to the Grid Tab Switcher when
-     *         Start surface refactor is enabled. Used to create overviewLayout if it has value,
-     *         otherwise will use the accessibility overview layout.
+     *     Start surface refactor is enabled. Used to create overviewLayout if it has value,
+     *     otherwise will use the accessibility overview layout.
      * @param browserControlsStateProvider The {@link BrowserControlsStateProvider} for top
-     *         controls.
+     *     controls.
      * @param tabContentManagerSupplier Supplier of the {@link TabContentManager} instance.
      * @param topUiThemeColorProvider {@link ThemeColorProvider} for top UI.
      * @param tabSwitcherScrimAnchor {@link ViewGroup} used by tab switcher layout to show scrim
-     *         when overview is visible.
+     *     when overview is visible.
      * @param scrimCoordinator {@link ScrimCoordinator} to show/hide scrim.
      * @param delayedTabSwitcherOrStartSurfaceCallable Callable to create StartSurface/GTS views.
+     * @param hubLayoutDependencyHolder The dependency holder for creating {@link HubLayout}.
      */
-    public LayoutManagerChrome(LayoutManagerHost host, ViewGroup contentContainer,
-            Supplier<StartSurface> startSurfaceSupplier, Supplier<TabSwitcher> tabSwitcherSupplier,
+    public LayoutManagerChrome(
+            LayoutManagerHost host,
+            ViewGroup contentContainer,
+            Supplier<StartSurface> startSurfaceSupplier,
+            Supplier<TabSwitcher> tabSwitcherSupplier,
             BrowserControlsStateProvider browserControlsStateProvider,
             ObservableSupplier<TabContentManager> tabContentManagerSupplier,
             Supplier<TopUiThemeColorProvider> topUiThemeColorProvider,
-            ViewGroup tabSwitcherScrimAnchor, ScrimCoordinator scrimCoordinator,
-            Callable<ViewGroup> delayedTabSwitcherOrStartSurfaceCallable) {
+            ViewGroup tabSwitcherScrimAnchor,
+            ScrimCoordinator scrimCoordinator,
+            Callable<ViewGroup> delayedTabSwitcherOrStartSurfaceCallable,
+            HubLayoutDependencyHolder hubLayoutDependencyHolder) {
         super(host, contentContainer, tabContentManagerSupplier, topUiThemeColorProvider);
 
         // Build Event Filter Handlers
         mToolbarSwipeHandler = createToolbarSwipeHandler(/* supportSwipeDown = */ true);
 
         mTabContentManagerSupplier = tabContentManagerSupplier;
-        mTabContentManagerSupplier.addObserver(new Callback<TabContentManager>() {
-            @Override
-            public void onResult(TabContentManager manager) {
-                manager.addThumbnailChangeListener((id) -> requestUpdate());
-                if (mOverviewLayout != null) {
-                    mOverviewLayout.setTabContentManager(manager);
-                }
-                if (mTabSwitcherLayout != null) {
-                    mTabSwitcherLayout.setTabContentManager(manager);
-                }
-                if (mStartSurfaceHomeLayout != null) {
-                    mStartSurfaceHomeLayout.setTabContentManager(manager);
-                }
-                tabContentManagerSupplier.removeObserver(this);
-            }
-        });
+        mTabContentManagerSupplier.addObserver(
+                new Callback<TabContentManager>() {
+                    @Override
+                    public void onResult(TabContentManager manager) {
+                        manager.addThumbnailChangeListener((id) -> requestUpdate());
+                        if (mOverviewLayout != null) {
+                            mOverviewLayout.setTabContentManager(manager);
+                        }
+                        if (mTabSwitcherLayout != null) {
+                            mTabSwitcherLayout.setTabContentManager(manager);
+                        }
+                        if (mStartSurfaceHomeLayout != null) {
+                            mStartSurfaceHomeLayout.setTabContentManager(manager);
+                        }
+                        if (mHubLayout != null) {
+                            mHubLayout.setTabContentManager(manager);
+                        }
+                        tabContentManagerSupplier.removeObserver(this);
+                    }
+                });
 
         mStartSurfaceSupplier = startSurfaceSupplier;
         mTabSwitcherSupplier = tabSwitcherSupplier;
         mScrimCoordinator = scrimCoordinator;
         mCreateTabSwitcherOrStartSurfaceCallable = delayedTabSwitcherOrStartSurfaceCallable;
+        mHubLayoutDependencyHolder = hubLayoutDependencyHolder;
 
         Context context = host.getContext();
         if (ReturnToChromeUtil.isStartSurfaceRefactorEnabled(context)) {
             if (mStartSurfaceSupplier.hasValue() || mTabSwitcherSupplier.hasValue()) {
-                createLayoutsForStartSurfaceAndTabSwitcher(mStartSurfaceSupplier.get(),
-                        mTabSwitcherSupplier.get(), browserControlsStateProvider, scrimCoordinator,
-                        tabSwitcherScrimAnchor);
+                createLayoutsForStartSurfaceAndTabSwitcher(
+                        mStartSurfaceSupplier.get(),
+                        mTabSwitcherSupplier.get(),
+                        browserControlsStateProvider,
+                        scrimCoordinator,
+                        tabSwitcherScrimAnchor,
+                        hubLayoutDependencyHolder);
             }
         } else if (mStartSurfaceSupplier.hasValue()) {
-            createLayoutsForStartSurfaceAndTabSwitcher(mStartSurfaceSupplier.get(),
-                    /*tabSwitcher=*/null, browserControlsStateProvider, scrimCoordinator,
-                    tabSwitcherScrimAnchor);
+            createLayoutsForStartSurfaceAndTabSwitcher(
+                    mStartSurfaceSupplier.get(),
+                    /* tabSwitcher= */ null,
+                    browserControlsStateProvider,
+                    scrimCoordinator,
+                    tabSwitcherScrimAnchor,
+                    hubLayoutDependencyHolder);
         }
     }
 
     /**
      * Creates {@link org.chromium.chrome.features.start_surface.TabSwitcherAndStartSurfaceLayout}
-     * or ({@link org.chromium.chrome.features.start_surface.StartSurfaceHomeLayout} AND
-     * {@link org.chromium.chrome.features.tasks.tab_management.TabSwitcherLayout}).
+     * or ({@link org.chromium.chrome.features.start_surface.StartSurfaceHomeLayout} AND {@link
+     * org.chromium.chrome.features.tasks.tab_management.TabSwitcherLayout}).
+     *
      * @param startSurface An interface to talk to the Grid Tab Switcher when Start surface refactor
-     *         is disabled.
+     *     is disabled.
      * @param tabSwitcher An interface to talk to the GridTabSwitcher when Start surface refactor is
-     *         enabled and DeferTabSwitcherLayoutCreation is disabled.
+     *     enabled and DeferTabSwitcherLayoutCreation is disabled.
      * @param browserControlsStateProvider The {@link BrowserControlsStateProvider} for top
-     *         controls.
+     *     controls.
      * @param scrimCoordinator scrim coordinator for GTS
      * @param tabSwitcherScrimAnchor scrim anchor view for GTS
+     * @param hubLayoutDependencyHolder The dependency holder for creating {@link HubLayout}.
      */
-    protected void createLayoutsForStartSurfaceAndTabSwitcher(@Nullable StartSurface startSurface,
+    protected void createLayoutsForStartSurfaceAndTabSwitcher(
+            @Nullable StartSurface startSurface,
             @Nullable TabSwitcher tabSwitcher,
             BrowserControlsStateProvider browserControlsStateProvider,
-            ScrimCoordinator scrimCoordinator, ViewGroup tabSwitcherScrimAnchor) {
-        assert mOverviewLayout == null && mTabSwitcherLayout == null
-                && mStartSurfaceHomeLayout == null;
+            ScrimCoordinator scrimCoordinator,
+            ViewGroup tabSwitcherScrimAnchor,
+            HubLayoutDependencyHolder hubLayoutDependencyHolder) {
+        assert mOverviewLayout == null
+                && mTabSwitcherLayout == null
+                && mStartSurfaceHomeLayout == null
+                && mHubLayout == null;
         boolean isRefactorEnabled =
                 ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mHost.getContext());
 
         if (isRefactorEnabled) {
             // TabSwitcherLayout creation is deferred until it is first shown.
             if (!ChromeFeatureList.sDeferTabSwitcherLayoutCreation.isEnabled()) {
-                assert tabSwitcher != null;
-                createTabSwitcherLayout(tabSwitcher, browserControlsStateProvider, scrimCoordinator,
-                        tabSwitcherScrimAnchor);
+                if (HubFieldTrial.isHubEnabled()) {
+                    createHubLayout(hubLayoutDependencyHolder);
+                } else {
+                    assert tabSwitcher != null;
+                    createTabSwitcherLayout(
+                            tabSwitcher,
+                            browserControlsStateProvider,
+                            scrimCoordinator,
+                            tabSwitcherScrimAnchor);
+                }
             }
             if (startSurface != null) {
                 createStartSurfaceHomeLayout(startSurface);
@@ -249,6 +294,29 @@
         }
     }
 
+    /** Creates {@link org.chromium.chrome.browser.hub.HubLayout}. */
+    protected void createHubLayout(@NonNull HubLayoutDependencyHolder hubLayoutDependencyHolder) {
+        Context context = mHost.getContext();
+        LayoutRenderHost renderHost = mHost.getLayoutRenderHost();
+
+        mHubLayout =
+                new HubLayout(
+                        context,
+                        /* updateHost= */ this,
+                        renderHost,
+                        /* layoutStateProvider= */ this,
+                        hubLayoutDependencyHolder);
+        if (mTabContentManagerSupplier.hasValue()) {
+            mHubLayout.setTabContentManager(mTabContentManagerSupplier.get());
+        }
+        if (getTabModelSelector() != null) {
+            mHubLayout.setTabModelSelector(getTabModelSelector());
+        }
+        if (mFinishNativeInitialization) {
+            mHubLayout.onFinishNativeInitialization();
+        }
+    }
+
     /**
      * Creates {@link org.chromium.chrome.features.start_surface.StartSurfaceHomeLayout}.
      * @param startSurface An interface to talk to the Grid Tab Switcher when Start surface refactor
@@ -384,13 +452,20 @@
             mStartSurfaceHomeLayout.setTabContentManager(content);
             mStartSurfaceHomeLayout.onFinishNativeInitialization();
         }
+        if (mHubLayout != null) {
+            mHubLayout.setTabModelSelector(selector);
+            mHubLayout.setTabContentManager(content);
+            mHubLayout.onFinishNativeInitialization();
+        }
         mFinishNativeInitialization = true;
     }
 
     @Override
     public void showLayout(int layoutType, boolean animate) {
-        if (layoutType == LayoutType.TAB_SWITCHER && mOverviewLayout == null
-                && mTabSwitcherLayout == null) {
+        if (layoutType == LayoutType.TAB_SWITCHER
+                && mOverviewLayout == null
+                && mTabSwitcherLayout == null
+                && mHubLayout == null) {
             initTabSwitcher();
         }
         super.showLayout(layoutType, animate);
@@ -402,23 +477,32 @@
      * refactor is enabled for phones.
      */
     private void initTabSwitcher() {
+        boolean isRefactorEnabled =
+                ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mHost.getContext());
+
+        // Implicitly guarded by sDeferTabSwitcherLayoutCreation as mTabSwitcherSupplier will
+        // have a value already if the feature is disabled.
+        if (mStartSurfaceSupplier.hasValue()
+                && (!isRefactorEnabled || mTabSwitcherSupplier.hasValue())) {
+            return;
+        }
+
+        if (isRefactorEnabled && HubFieldTrial.isHubEnabled()) {
+            createHubLayout(mHubLayoutDependencyHolder);
+            return;
+        }
+
         try {
-            boolean isRefactorEnabled =
-                    ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mHost.getContext());
-
-            // Implicitly guarded by sDeferTabSwitcherLayoutCreation as mTabSwitcherSupplier will
-            // have a value already if the feature is disabled.
-            if (mStartSurfaceSupplier.hasValue()
-                    && (!isRefactorEnabled || mTabSwitcherSupplier.hasValue())) {
-                return;
-            }
-
             final ViewGroup containerView = mCreateTabSwitcherOrStartSurfaceCallable.call();
+
             if (isRefactorEnabled) {
                 final TabSwitcher tabSwitcher = mTabSwitcherSupplier.get();
                 assert tabSwitcher != null;
-                createTabSwitcherLayout(tabSwitcher, mHost.getBrowserControlsManager(),
-                        mScrimCoordinator, containerView);
+                createTabSwitcherLayout(
+                        tabSwitcher,
+                        mHost.getBrowserControlsManager(),
+                        mScrimCoordinator,
+                        containerView);
             } else {
                 final StartSurface startSurface = mStartSurfaceSupplier.get();
                 assert startSurface != null;
@@ -449,6 +533,9 @@
         if (mStartSurfaceHomeLayout != null) {
             mStartSurfaceHomeLayout.setTabModelSelector(selector);
         }
+        if (mHubLayout != null) {
+            mHubLayout.setTabModelSelector(selector);
+        }
     }
 
     @Override
@@ -476,6 +563,10 @@
             mStartSurfaceHomeLayout.destroy();
             mStartSurfaceHomeLayout = null;
         }
+        if (mHubLayout != null) {
+            mHubLayout.destroy();
+            mHubLayout = null;
+        }
         if (mToolbarSwipeLayout != null) {
             mToolbarSwipeLayout.destroy();
         }
@@ -492,7 +583,9 @@
         if (layoutType == LayoutType.TOOLBAR_SWIPE) {
             layout = mToolbarSwipeLayout;
         } else if (layoutType == LayoutType.TAB_SWITCHER) {
-            if (mTabSwitcherLayout != null) {
+            if (mHubLayout != null) {
+                layout = mHubLayout;
+            } else if (mTabSwitcherLayout != null) {
                 layout = mTabSwitcherLayout;
             } else {
                 layout = mOverviewLayout;
@@ -720,7 +813,9 @@
         private boolean isTabSwitcherReady() {
             // On Tablets, or with Start Surface Refactor, attempting to show the GTS while it's
             // null will trigger its creation.
-            return mOverviewLayout != null || mTabSwitcherLayout != null
+            return mOverviewLayout != null
+                    || mTabSwitcherLayout != null
+                    || mHubLayout != null
                     || DeviceFormFactor.isNonMultiDisplayContextOnTablet(mHost.getContext())
                     || (ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mHost.getContext())
                             && ChromeFeatureList.sDeferTabSwitcherLayoutCreation.isEnabled());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
index de8c927d..33988b93 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
@@ -12,6 +12,7 @@
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.compositor.layouts.phone.SimpleAnimationLayout;
+import org.chromium.chrome.browser.hub.HubLayoutDependencyHolder;
 import org.chromium.chrome.browser.layouts.LayoutType;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
@@ -34,30 +35,45 @@
 
     /**
      * Creates an instance of a {@link LayoutManagerChromePhone}.
-     * @param host         A {@link LayoutManagerHost} instance.
+     *
+     * @param host A {@link LayoutManagerHost} instance.
      * @param contentContainer A {@link ViewGroup} for Android views to be bound to.
      * @param startSurfaceSupplier Supplier for an interface to talk to the Grid Tab Switcher when
-     *         Start surface refactor is disabled. Used to create overviewLayout if it has value,
-     *         otherwise will use the accessibility overview layout.
+     *     Start surface refactor is disabled. Used to create overviewLayout if it has value,
+     *     otherwise will use the accessibility overview layout.
      * @param tabSwitcherSupplier Supplier for an interface to talk to the Grid Tab Switcher when
-     *         Start surface refactor is enabled. Used to create overviewLayout if it has value,
-     *         otherwise will use the accessibility overview layout.
+     *     Start surface refactor is enabled. Used to create overviewLayout if it has value,
+     *     otherwise will use the accessibility overview layout.
      * @param browserControlsStateProvider The {@link BrowserControlsStateProvider} for top
-     *         controls.
+     *     controls.
      * @param tabContentManagerSupplier Supplier of the {@link TabContentManager} instance.
      * @param topUiThemeColorProvider {@link ThemeColorProvider} for top UI.
      * @param delayedTabSwitcherCallable Callable to create GTS view if Start Surface refactor and
-     *         DeferCreateTabSwitcherLayout are enabled.
+     *     DeferCreateTabSwitcherLayout are enabled.
+     * @param hubLayoutDependencyHolder The dependency holder for creating {@link HubLayout}.
      */
-    public LayoutManagerChromePhone(LayoutManagerHost host, ViewGroup contentContainer,
-            Supplier<StartSurface> startSurfaceSupplier, Supplier<TabSwitcher> tabSwitcherSupplier,
+    public LayoutManagerChromePhone(
+            LayoutManagerHost host,
+            ViewGroup contentContainer,
+            Supplier<StartSurface> startSurfaceSupplier,
+            Supplier<TabSwitcher> tabSwitcherSupplier,
             BrowserControlsStateProvider browserControlsStateProvider,
             ObservableSupplier<TabContentManager> tabContentManagerSupplier,
             Supplier<TopUiThemeColorProvider> topUiThemeColorProvider,
-            Callable<ViewGroup> delayedTabSwitcherCallable) {
-        super(host, contentContainer, startSurfaceSupplier, tabSwitcherSupplier,
-                browserControlsStateProvider, tabContentManagerSupplier, topUiThemeColorProvider,
-                null, null, delayedTabSwitcherCallable);
+            Callable<ViewGroup> delayedTabSwitcherCallable,
+            HubLayoutDependencyHolder hubLayoutDependencyHolder) {
+        super(
+                host,
+                contentContainer,
+                startSurfaceSupplier,
+                tabSwitcherSupplier,
+                browserControlsStateProvider,
+                tabContentManagerSupplier,
+                topUiThemeColorProvider,
+                null,
+                null,
+                delayedTabSwitcherCallable,
+                hubLayoutDependencyHolder);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
index 98177a5..9c60506 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
@@ -18,6 +18,7 @@
 import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager;
 import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager.TabModelStartupInfo;
 import org.chromium.chrome.browser.device.DeviceClassManager;
+import org.chromium.chrome.browser.hub.HubLayoutDependencyHolder;
 import org.chromium.chrome.browser.layouts.LayoutType;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.multiwindow.MultiInstanceManager;
@@ -68,6 +69,7 @@
      * @param lifecycleDispatcher @{@link ActivityLifecycleDispatcher} to be passed to TabStrip
      *     helper.
      * @param delayedTabSwitcherOrStartSurfaceCallable Callable to create StartSurface/GTS views.
+     * @param hubLayoutDependencyHolder The dependency holder for creating {@link HubLayout}.
      * @param multiInstanceManager @{link MultiInstanceManager} passed to @{link StripLayoutHelper}
      *     to support tab drag and drop.
      * @param dragAndDropDelegate @{@link DragAndDropDelegate} passed to {@link
@@ -89,13 +91,23 @@
             ScrimCoordinator scrimCoordinator,
             ActivityLifecycleDispatcher lifecycleDispatcher,
             Callable<ViewGroup> delayedTabSwitcherOrStartSurfaceCallable,
+            HubLayoutDependencyHolder hubLayoutDependencyHolder,
             MultiInstanceManager multiInstanceManager,
             DragAndDropDelegate dragAndDropDelegate,
             View toolbarContainerView,
             @NonNull ViewStub tabHoverCardViewStub) {
-        super(host, contentContainer, startSurfaceSupplier, tabSwitcherSupplier,
-                browserControlsStateProvider, tabContentManagerSupplier, topUiThemeColorProvider,
-                tabSwitcherViewHolder, scrimCoordinator, delayedTabSwitcherOrStartSurfaceCallable);
+        super(
+                host,
+                contentContainer,
+                startSurfaceSupplier,
+                tabSwitcherSupplier,
+                browserControlsStateProvider,
+                tabContentManagerSupplier,
+                topUiThemeColorProvider,
+                tabSwitcherViewHolder,
+                scrimCoordinator,
+                delayedTabSwitcherOrStartSurfaceCallable,
+                hubLayoutDependencyHolder);
         mTabStripLayoutHelperManager =
                 new StripLayoutHelperManager(
                         host.getContext(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/ChromeDirectActionIds.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/ChromeDirectActionIds.java
deleted file mode 100644
index 5d8ee25e..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/ChromeDirectActionIds.java
+++ /dev/null
@@ -1,58 +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.chrome.browser.directactions;
-
-/**
- * Set of core Chrome direct actions, introduced in this package.
- *
- * <p>This is not the full set of direct actions potentially available in Chrome. The full set might
- * not even be available at compile time. For an up-to-date list, see
- * http://go.ext.google.com/chrome-direct-action-list Please update this list when adding a new
- * direct action to this set.
- */
-public class ChromeDirectActionIds {
-    // Equivalent to pressing the go back button. Always available.
-    public static final String GO_BACK = "go_back";
-
-    // Reload the current tab.
-    public static final String RELOAD = "reload";
-
-    // Navigate the current tab's document forward.
-    public static final String GO_FORWARD = "go_forward";
-
-    // Add or update the bookmark for the current page on the current table.
-    public static final String BOOKMARK_THIS_PAGE = "bookmark_this_page";
-
-    // Open the downloads page.
-    public static final String DOWNLOADS = "downloads";
-
-    // Open the preferences dialog.
-    public static final String PREFERENCES = "preferences";
-
-    // Open the history page.
-    public static final String OPEN_HISTORY = "open_history";
-
-    // Display the help and feedback dialog appropriate for the current tab.
-    public static final String HELP = "help";
-
-    // Open a new tab.
-    public static final String NEW_TAB = "new_tab";
-
-    // Close the current tab.
-    public static final String CLOSE_TAB = "close_tab";
-
-    // Close all tabs
-    public static final String CLOSE_ALL_TABS = "close_all_tabs";
-
-    // Find in page.
-    public static final String FIND_IN_PAGE = "find_in_page";
-
-    // If you add a new action to this list, consider extending ChromeDirectActionUsageHistogram to
-    // track usage of the new action.
-
-    private ChromeDirectActionIds() {
-        // This is a utility class. It is not meant to be instantiated.
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandler.java
deleted file mode 100644
index 9dafc77b..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandler.java
+++ /dev/null
@@ -1,38 +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.chrome.browser.directactions;
-
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-
-/**
- * Exposes direct actions that allows closing tabs.
- *
- * <p>This should only be registered in activities where such an action makes sense.
- */
-class CloseTabDirectActionHandler extends SimpleDirectActionHandler {
-    private final TabModelSelector mTabModelSelector;
-
-    CloseTabDirectActionHandler(TabModelSelector tabModelSelector) {
-        super(ChromeDirectActionIds.CLOSE_TAB);
-
-        mTabModelSelector = tabModelSelector;
-    }
-
-    @Override
-    protected boolean isAvailable() {
-        return mTabModelSelector.getCurrentTab() != null;
-    }
-
-    @Override
-    public void run() {
-        Tab tab = mTabModelSelector.getCurrentTab();
-        assert tab != null; // isAvailable() guarantees tab is non-null
-
-        TabModel model = mTabModelSelector.getCurrentModel();
-        model.closeTab(tab, /* animate= */ true, /* uponExit= */ false, /* canUndo= */ true);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionCoordinator.java
deleted file mode 100644
index d099cf5..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionCoordinator.java
+++ /dev/null
@@ -1,88 +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.chrome.browser.directactions;
-
-import android.os.Bundle;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-
-import org.chromium.base.Callback;
-import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.base.supplier.Supplier;
-
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Consumer;
-
-/**
- * Reports available direct actions and executes them.
- *
- * <p>Handlers can define any direct action they want, but the client of direct actions need to be
- * aware of them to make use of them. For this to work, if you add a new action here, please list it
- * and document it in http://go.ext.google.com/chrome-direct-action-list
- */
-@RequiresApi(29)
-public abstract class DirectActionCoordinator {
-    private final Set<DirectActionHandler> mHandlers = new LinkedHashSet<>();
-
-    /**
-     * Dynamic check of whether direct actions should be enabled. This is run before every call.
-     *
-     * <p>During startup, assume direct actions are disabled until initialized.
-     */
-    private Supplier<Boolean> mIsEnabled = () -> false;
-
-    /** Registers a handler. */
-    public void register(DirectActionHandler handler) {
-        mHandlers.add(handler);
-    }
-
-    /** Unregisters a handler. */
-    public void unregister(DirectActionHandler handler) {
-        mHandlers.remove(handler);
-    }
-
-    /** Sends a list of supported actions to the given callback. */
-    public final void onGetDirectActions(Consumer<List> callback) {
-        DirectActionReporter reporter = createReporter(callback);
-        if (mIsEnabled.get()) {
-            for (DirectActionHandler handler : mHandlers) {
-                handler.reportAvailableDirectActions(reporter);
-            }
-        }
-        reporter.report();
-        RecordUserAction.record("Android.DirectAction.List");
-    }
-
-    /** Performs an action and reports the result to the callback. */
-    public final void onPerformDirectAction(
-            String actionId, Bundle arguments, Consumer<Bundle> consumer) {
-        if (!mIsEnabled.get()) return;
-
-        boolean performedAction = false;
-        Callback<Bundle> callback = (result) -> consumer.accept(result);
-        for (DirectActionHandler handler : mHandlers) {
-            if (handler.performDirectAction(actionId, arguments, callback)) {
-                performedAction = true;
-                break;
-            }
-        }
-        if (performedAction) {
-            DirectActionUsageHistogram.record(actionId);
-        } else {
-            DirectActionUsageHistogram.recordUnknown();
-        }
-    }
-
-    /** Subclasses should provide an implementation of a DirectActionReporter. */
-    protected abstract DirectActionReporter createReporter(Consumer<List> callback);
-
-    /** Initializes the coordinator. */
-    void init(@NonNull Supplier<Boolean> isEnabled) {
-        mIsEnabled = isEnabled;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionHandler.java
deleted file mode 100644
index ae50d2ae..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionHandler.java
+++ /dev/null
@@ -1,30 +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.chrome.browser.directactions;
-
-import android.os.Bundle;
-
-import org.chromium.base.Callback;
-
-/**
- * Implements the reporting and handling of a set of direct actions.
- *
- * Handlers available for the current activity should be registered to that activity's {@link
- * DirectActionCoordinator}.
- */
-public interface DirectActionHandler {
-    /** Reports currently available actions. */
-    void reportAvailableDirectActions(DirectActionReporter reporter);
-
-    /**
-     * Perform the action identified {@code actionId}, if supported by this handler.
-     *
-     * @param actionId The action identifier
-     * @param arguments Argument provided by the caller
-     * @param callback Callback to report the result of the action to
-     * @return true if the action was handled by this handler.
-     */
-    boolean performDirectAction(String actionId, Bundle arguments, Callback<Bundle> callback);
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionInitializer.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionInitializer.java
deleted file mode 100644
index 7b41716..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionInitializer.java
+++ /dev/null
@@ -1,189 +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.chrome.browser.directactions;
-
-import android.os.Bundle;
-import android.os.CancellationSignal;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.AppHooks;
-import org.chromium.chrome.browser.findinpage.FindToolbarManager;
-import org.chromium.chrome.browser.flags.ActivityType;
-import org.chromium.chrome.browser.lifecycle.DestroyObserver;
-import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.function.Consumer;
-
-/**
- * A wrapper for initializing {@link DirectActionCoordinator} with standard direct actions from
- * Chrome activities.
- *
- * <p>To extend the set of direct actions beyond what's provided by this class, register handlers to
- * the coordinator {@code mCoordinator}.
- */
-@RequiresApi(29)
-public class DirectActionInitializer implements NativeInitObserver, DestroyObserver {
-    private final TabModelSelector mTabModelSelector;
-
-    @ActivityType
-    private int mActivityType;
-    private MenuOrKeyboardActionController mMenuOrKeyboardActionController;
-    private Runnable mGoBackAction;
-    @Nullable
-    private FindToolbarManager mFindToolbarManager;
-    private boolean mDirectActionsRegistered;
-    @Nullable
-    private DirectActionCoordinator mCoordinator;
-    @Nullable
-    private MenuDirectActionHandler mMenuHandler;
-
-    /**
-     * @param activityType The type of the current activity
-     * @param actionController Controller to use to execute menu actions
-     * @param goBackAction Implementation of the "go_back" action, usually {@link
-     *         android.app.Activity#onBackPressed}.
-     * @param tabModelSelector The activity's {@link TabModelSelector}
-     * @param findToolbarManager Manager to use for the "find_in_page" action, if it exists
-     */
-    public DirectActionInitializer(@ActivityType int activityType,
-            MenuOrKeyboardActionController actionController, Runnable goBackAction,
-            TabModelSelector tabModelSelector, @Nullable FindToolbarManager findToolbarManager) {
-        mActivityType = activityType;
-        mMenuOrKeyboardActionController = actionController;
-        mGoBackAction = goBackAction;
-        mTabModelSelector = tabModelSelector;
-        mFindToolbarManager = findToolbarManager;
-
-        mDirectActionsRegistered = false;
-    }
-
-    /**
-     * Performs a direct action.
-     *
-     * @param actionId Name of the direct action to perform.
-     * @param arguments Arguments for this action.
-     * @param cancellationSignal Signal used to cancel a direct action from the caller.
-     * @param callback Callback to run when the action is done.
-     */
-    public void onPerformDirectAction(String actionId, Bundle arguments,
-            CancellationSignal cancellationSignal, Consumer<Bundle> callback) {
-        if (mCoordinator == null || !mDirectActionsRegistered) {
-            callback.accept(Bundle.EMPTY);
-            return;
-        }
-        mCoordinator.onPerformDirectAction(actionId, arguments, callback);
-    }
-
-    /**
-     * Lists direct actions supported.
-     *
-     * Returns a list of direct actions supported by the Activity associated with this
-     * RootUiCoordinator.
-     *
-     * @param cancellationSignal Signal used to cancel a direct action from the caller.
-     * @param callback Callback to run when the action is done.
-     */
-    public void onGetDirectActions(CancellationSignal cancellationSignal, Consumer<List> callback) {
-        if (mCoordinator == null || !mDirectActionsRegistered) {
-            callback.accept(Collections.emptyList());
-            return;
-        }
-        mCoordinator.onGetDirectActions(callback);
-    }
-
-    /**
-     * Registers common action that manipulate the current activity or the browser content.
-     *
-     * @param actionController Controller to use to execute menu actions
-     * @param goBackAction Implementation of the "go_back" action, usually {@link
-     *         android.app.Activity#onBackPressed}.
-     * @param tabModelSelector The activity's {@link TabModelSelector}
-     * @param findToolbarManager Manager to use for the "find_in_page" action, if it exists
-     */
-    private void registerCommonChromeActions(MenuOrKeyboardActionController actionController,
-            Runnable goBackAction, TabModelSelector tabModelSelector,
-            @Nullable FindToolbarManager findToolbarManager) {
-        mCoordinator.register(new GoBackDirectActionHandler(goBackAction));
-        mCoordinator.register(
-                new FindInPageDirectActionHandler(tabModelSelector, findToolbarManager));
-
-        registerMenuHandlerIfNecessary(actionController, tabModelSelector)
-                .allowlistActions(R.id.forward_menu_id, R.id.reload_menu_id);
-    }
-
-    /**
-     * Registers actions that manipulate tabs in addition to the common actions.
-     *
-     * @param actionController Controller to use to execute menu action
-     * @param tabModelSelector The activity's {@link TabModelSelector}
-     */
-    void registerTabManipulationActions(
-            MenuOrKeyboardActionController actionController, TabModelSelector tabModelSelector) {
-        registerMenuHandlerIfNecessary(actionController, tabModelSelector).allowAllActions();
-        mCoordinator.register(new CloseTabDirectActionHandler(tabModelSelector));
-    }
-
-    /**
-     * Allows a specific set of menu actions in addition to the common actions.
-     *
-     * @param actionController Controller to use to execute menu action
-     * @param tabModelSelector The activity's {@link TabModelSelector}
-     */
-    void allowMenuActions(MenuOrKeyboardActionController actionController,
-            TabModelSelector tabModelSelector, Integer... itemIds) {
-        registerMenuHandlerIfNecessary(actionController, tabModelSelector)
-                .allowlistActions(itemIds);
-    }
-
-    // Implements DestroyObserver
-    @Override
-    public void onDestroy() {
-        mCoordinator = null;
-        mDirectActionsRegistered = false;
-    }
-
-    // Implements NativeInitObserver
-    @Override
-    public void onFinishNativeInitialization() {
-        mCoordinator = AppHooks.get().createDirectActionCoordinator();
-        if (mCoordinator != null) {
-            mCoordinator.init(/* isEnabled= */ () -> !mTabModelSelector.isIncognitoSelected());
-            registerDirectActions();
-        }
-    }
-
-    /**
-     * Registers the set of direct actions available to assist apps.
-     */
-    void registerDirectActions() {
-        registerCommonChromeActions(mMenuOrKeyboardActionController, mGoBackAction,
-                mTabModelSelector, mFindToolbarManager);
-
-        if (mActivityType == ActivityType.TABBED) {
-            registerTabManipulationActions(mMenuOrKeyboardActionController, mTabModelSelector);
-        } else if (mActivityType == ActivityType.CUSTOM_TAB) {
-            allowMenuActions(mMenuOrKeyboardActionController, mTabModelSelector,
-                    R.id.bookmark_this_page_id, R.id.preferences_id);
-        }
-
-        mDirectActionsRegistered = true;
-    }
-
-    private MenuDirectActionHandler registerMenuHandlerIfNecessary(
-            MenuOrKeyboardActionController actionController, TabModelSelector tabModelSelector) {
-        if (mMenuHandler == null) {
-            mMenuHandler = new MenuDirectActionHandler(actionController, tabModelSelector);
-            mCoordinator.register(mMenuHandler);
-        }
-        return mMenuHandler;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionReporter.java
deleted file mode 100644
index 9b3b987..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionReporter.java
+++ /dev/null
@@ -1,71 +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.chrome.browser.directactions;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.RequiresApi;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * A helper for reporting simple direct actions to {@code Activity.onGetDirectActions}.
- *
- * <p>This is not a generic API; it only supports the subset of action schema Chrome actually needs.
- *
- * <h2>Usage example</h2>
- *
- * <pre>
- * void onGetDirectActions(..., Consumer<List> callback) {
- *   DirectActionReporter reporter = new ...
- *   reporter.addDirectAction("noarg");
- *   reporter.addDirectAction("withargs")
- *       .withParameter("arg1_required", Type.STRING, true)
- *       .withParameter("arg2_optional", Type.STRING, false);
- *   reporter.addDirectAction("return_bool").withResult("result", Type.BOOLEAN);
- *   reporter.report();
- * }
- * </pre>
- *
- * <p>This class produces lists of {@code android.app.DirectAction}. Since this class is only
- * available starting with API 29, this class accesses these as {@link List}, without specifying the
- * instance type, to allow compiling against older SDKs. TODO(crbug.com/973781): Clean it up once
- * Chromium is compiled against Android Q SDK.
- */
-@RequiresApi(29)
-public interface DirectActionReporter {
-    /** Parameter or result type. */
-    @IntDef({Type.STRING, Type.BOOLEAN, Type.INT})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Type {
-        int STRING = 0;
-        int BOOLEAN = 1;
-        int INT = 2;
-
-        /** The number of types. Increment this value if you add a type. */
-        int NUM_ENTRIES = 3;
-    }
-
-    /** Report the direct actions to the callback. */
-    void report();
-
-    /**
-     * Adds a direct action to report. The returned definition can be modified until the actions are
-     * reported.
-     *
-     * <p>Adding a definition for direct action with the same name as an existing one replaces the
-     * previous definition.
-     */
-    Definition addDirectAction(String name);
-
-    /** Definition of a direct action to which arguments and results can be added. */
-    interface Definition {
-        /** Declares a parameter for the current action. */
-        Definition withParameter(String name, @Type int type, boolean required);
-
-        /** Declares a result for the current action. */
-        Definition withResult(String name, @Type int type);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionUsageHistogram.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionUsageHistogram.java
deleted file mode 100644
index b0f3276..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionUsageHistogram.java
+++ /dev/null
@@ -1,101 +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.chrome.browser.directactions;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.VisibleForTesting;
-
-import org.chromium.base.metrics.RecordHistogram;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A histogram that tracks calls to {@link ChromeActivity#onPerformDirectAction} and, when possible,
- * the specific action that was performed.
- */
-class DirectActionUsageHistogram {
-
-    /** A map that convert known string ids to enum value for the histogram. */
-    private static final Map<String, Integer> ACTION_ID_MAP;
-    static {
-        Map<String, Integer> map = new HashMap<>();
-        map.put(ChromeDirectActionIds.GO_BACK, DirectActionId.GO_BACK);
-        map.put(ChromeDirectActionIds.RELOAD, DirectActionId.RELOAD);
-        map.put(ChromeDirectActionIds.GO_FORWARD, DirectActionId.GO_FORWARD);
-        map.put(ChromeDirectActionIds.BOOKMARK_THIS_PAGE, DirectActionId.BOOKMARK_THIS_PAGE);
-        map.put(ChromeDirectActionIds.DOWNLOADS, DirectActionId.DOWNLOADS);
-        map.put(ChromeDirectActionIds.PREFERENCES, DirectActionId.PREFERENCES);
-        map.put(ChromeDirectActionIds.OPEN_HISTORY, DirectActionId.OPEN_HISTORY);
-        map.put(ChromeDirectActionIds.HELP, DirectActionId.HELP);
-        map.put(ChromeDirectActionIds.NEW_TAB, DirectActionId.NEW_TAB);
-        map.put(ChromeDirectActionIds.CLOSE_TAB, DirectActionId.CLOSE_TAB);
-        map.put(ChromeDirectActionIds.CLOSE_ALL_TABS, DirectActionId.CLOSE_ALL_TABS);
-        map.put(ChromeDirectActionIds.FIND_IN_PAGE, DirectActionId.FIND_IN_PAGE);
-        ACTION_ID_MAP = Collections.unmodifiableMap(map);
-    }
-
-    /**
-     * Enum defined in tools/metrics/histograms/enums.xml.
-     */
-    @VisibleForTesting
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({DirectActionId.GO_BACK, DirectActionId.RELOAD, DirectActionId.GO_FORWARD,
-            DirectActionId.BOOKMARK_THIS_PAGE, DirectActionId.DOWNLOADS, DirectActionId.PREFERENCES,
-            DirectActionId.OPEN_HISTORY, DirectActionId.HELP, DirectActionId.NEW_TAB,
-            DirectActionId.CLOSE_TAB, DirectActionId.CLOSE_ALL_TABS, DirectActionId.FIND_IN_PAGE,
-            DirectActionId.NUM_ENTRIES})
-    @interface DirectActionId {
-        /** No action was executed. */
-        int UNKNOWN = 0;
-
-        /** An action was executed that isn't in this enum. */
-        int OTHER = 1;
-
-        // Actions from ChromeDirectActionIds.
-        int GO_BACK = 2;
-        int RELOAD = 3;
-        int GO_FORWARD = 4;
-        int BOOKMARK_THIS_PAGE = 5;
-        int DOWNLOADS = 6;
-        int PREFERENCES = 7;
-        int OPEN_HISTORY = 8;
-        int HELP = 9;
-        int NEW_TAB = 10;
-        int CLOSE_TAB = 11;
-        int CLOSE_ALL_TABS = 12;
-        int FIND_IN_PAGE = 13;
-
-        int NUM_ENTRIES = 14;
-    }
-
-    /**
-     * Records an attempt to execute a direct action that was rejected as unknown.
-     */
-    static void recordUnknown() {
-        record(DirectActionId.UNKNOWN);
-    }
-
-    /**
-     * Records direct action usage.
-     *
-     * @param actionId The string id of the direct action that was executed.
-     */
-    static void record(String actionId) {
-        @DirectActionId
-        Integer histogramId = ACTION_ID_MAP.get(actionId);
-        if (histogramId == null) histogramId = DirectActionId.OTHER;
-
-        record(histogramId);
-    }
-
-    private static void record(@DirectActionId int actionId) {
-        RecordHistogram.recordEnumeratedHistogram(
-                "Android.DirectAction.Perform", actionId, DirectActionId.NUM_ENTRIES);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/FindInPageDirectActionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/FindInPageDirectActionHandler.java
deleted file mode 100644
index 9a9fdc70..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/FindInPageDirectActionHandler.java
+++ /dev/null
@@ -1,61 +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.chrome.browser.directactions;
-
-import android.os.Bundle;
-import android.text.TextUtils;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.browser.directactions.DirectActionReporter.Type;
-import org.chromium.chrome.browser.findinpage.FindToolbarManager;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-
-/**
- * Maps the direct action {@code find_in_page} to Chrome's find in page feature.
- */
-public class FindInPageDirectActionHandler implements DirectActionHandler {
-    private static final String ACTION_ID = ChromeDirectActionIds.FIND_IN_PAGE;
-    private static final String ARGUMENT_NAME = "SEARCH_QUERY";
-
-    private final TabModelSelector mTabModelSelector;
-    private final FindToolbarManager mFindToolbarManager;
-
-    public FindInPageDirectActionHandler(
-            TabModelSelector tabModelSelector, FindToolbarManager findToolbarManager) {
-        mTabModelSelector = tabModelSelector;
-        mFindToolbarManager = findToolbarManager;
-    }
-
-    @Override
-    public final void reportAvailableDirectActions(DirectActionReporter reporter) {
-        if (isAvailable()) {
-            reporter.addDirectAction(ACTION_ID).withParameter(
-                    ARGUMENT_NAME, Type.STRING, /* required = */ true);
-        }
-    }
-
-    @Override
-    public final boolean performDirectAction(
-            String actionId, Bundle arguments, Callback<Bundle> callback) {
-        if (!ACTION_ID.equals(actionId)) return false;
-
-        if (!isAvailable()) return false;
-
-        mFindToolbarManager.showToolbar();
-        String findText = arguments.getString(ARGUMENT_NAME, "");
-        if (!TextUtils.isEmpty(findText)) {
-            mFindToolbarManager.setFindQuery(findText);
-        }
-        callback.onResult(Bundle.EMPTY);
-        return true;
-    }
-
-    /** Returns {@code true} if the action is currently available. */
-    private final boolean isAvailable() {
-        Tab tab = mTabModelSelector.getCurrentTab();
-        return tab != null && !tab.isNativePage() && tab.getWebContents() != null;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/GoBackDirectActionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/GoBackDirectActionHandler.java
deleted file mode 100644
index a1a2827..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/GoBackDirectActionHandler.java
+++ /dev/null
@@ -1,30 +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.chrome.browser.directactions;
-
-/**
- * Maps the direct action {@code go_back} to the same behavior as the one defined when pressing the
- * back button.
- */
-public class GoBackDirectActionHandler extends SimpleDirectActionHandler {
-    private final Runnable mAction;
-
-    public GoBackDirectActionHandler(Runnable action) {
-        super(ChromeDirectActionIds.GO_BACK);
-
-        mAction = action;
-    }
-
-    @Override
-    protected boolean isAvailable() {
-        // "go back" is always available
-        return true;
-    }
-
-    @Override
-    protected void run() {
-        mAction.run();
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/MenuDirectActionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/MenuDirectActionHandler.java
deleted file mode 100644
index 45da3c3..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/MenuDirectActionHandler.java
+++ /dev/null
@@ -1,120 +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.chrome.browser.directactions;
-
-import android.os.Bundle;
-
-import androidx.annotation.Nullable;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Exposes some well-known menu actions as direct actions.
- *
- * <p>This handler exposes a subset of available menu item actions, exposed by the given {@link
- * MenuOrKeyboardActionController}. By default, no actions are exposed; call {@link
- * #allowlistActions} or {@link #allowAllActions} to enable them.
- */
-class MenuDirectActionHandler implements DirectActionHandler {
-    /** Maps some menu item actions to direct actions. */
-    private static final Map<String, Integer> ACTION_MAP;
-    static {
-        Map<String, Integer> map = new HashMap<>();
-        map.put(ChromeDirectActionIds.GO_FORWARD, R.id.forward_menu_id);
-        map.put(ChromeDirectActionIds.RELOAD, R.id.reload_menu_id);
-        map.put(ChromeDirectActionIds.BOOKMARK_THIS_PAGE, R.id.bookmark_this_page_id);
-        map.put(ChromeDirectActionIds.DOWNLOADS, R.id.downloads_menu_id);
-        map.put(ChromeDirectActionIds.HELP, R.id.help_id);
-        map.put(ChromeDirectActionIds.NEW_TAB, R.id.new_tab_menu_id);
-        map.put(ChromeDirectActionIds.OPEN_HISTORY, R.id.open_history_menu_id);
-        map.put(ChromeDirectActionIds.PREFERENCES, R.id.preferences_id);
-        map.put(ChromeDirectActionIds.CLOSE_ALL_TABS, R.id.close_all_tabs_menu_id);
-        ACTION_MAP = Collections.unmodifiableMap(map);
-    }
-
-    private final MenuOrKeyboardActionController mMenuOrKeyboardActionController;
-    private final TabModelSelector mTabModelSelector;
-
-    /** If non-null, only actions that belong to this allowlist are available. */
-    @Nullable
-    private Set<Integer> mActionIdAllowlist = new HashSet<>();
-
-    MenuDirectActionHandler(MenuOrKeyboardActionController menuOrKeyboardActionController,
-            TabModelSelector tabModelSelector) {
-        this.mMenuOrKeyboardActionController = menuOrKeyboardActionController;
-        this.mTabModelSelector = tabModelSelector;
-    }
-
-    /** Allows the use of all known actions. */
-    void allowAllActions() {
-        mActionIdAllowlist = null;
-    }
-
-    /**
-     * Allows the use of the specified action, identified by their menu item id.
-     *
-     * <p>Does nothing if the actions are already available.
-     */
-    void allowlistActions(Integer... itemIds) {
-        if (mActionIdAllowlist == null) return;
-
-        for (int itemId : itemIds) {
-            mActionIdAllowlist.add(itemId);
-        }
-    }
-
-    @Override
-    public void reportAvailableDirectActions(DirectActionReporter reporter) {
-        Set<Integer> availableItemIds = new HashSet<>();
-        Tab currentTab = mTabModelSelector.getCurrentTab();
-        if (currentTab != null && currentTab.isUserInteractable()) {
-            if (currentTab.canGoForward()) {
-                availableItemIds.add(R.id.forward_menu_id);
-            }
-            availableItemIds.add(R.id.reload_menu_id);
-            availableItemIds.add(R.id.bookmark_this_page_id);
-            availableItemIds.add(R.id.open_history_menu_id);
-        }
-        if (mTabModelSelector.getTotalTabCount() > 0) {
-            availableItemIds.add(R.id.close_all_tabs_menu_id);
-        }
-
-        availableItemIds.add(R.id.downloads_menu_id);
-        availableItemIds.add(R.id.help_id);
-        availableItemIds.add(R.id.new_tab_menu_id);
-        availableItemIds.add(R.id.preferences_id);
-
-        if (mActionIdAllowlist != null) availableItemIds.retainAll(mActionIdAllowlist);
-
-        for (Map.Entry<String, Integer> entry : ACTION_MAP.entrySet()) {
-            if (availableItemIds.contains(entry.getValue())) {
-                reporter.addDirectAction(entry.getKey());
-            }
-        }
-    }
-
-    @Override
-    public boolean performDirectAction(
-            String actionId, Bundle arguments, Callback<Bundle> callback) {
-        Integer menuId = ACTION_MAP.get(actionId);
-        if (menuId != null && (mActionIdAllowlist == null || mActionIdAllowlist.contains(menuId))
-                && mMenuOrKeyboardActionController.onMenuOrKeyboardAction(
-                        menuId, /* fromMenu= */ false)) {
-            callback.onResult(Bundle.EMPTY);
-            return true;
-        }
-        return false;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/SimpleDirectActionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/SimpleDirectActionHandler.java
deleted file mode 100644
index b025db7a..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/SimpleDirectActionHandler.java
+++ /dev/null
@@ -1,48 +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.chrome.browser.directactions;
-
-import android.os.Bundle;
-
-import org.chromium.base.Callback;
-
-/**
- * Abstract base class that helps define handler that provide a single, no-argument action,
- * implemented synchronously.
- */
-public abstract class SimpleDirectActionHandler implements DirectActionHandler {
-    private final String mActionId;
-
-    public SimpleDirectActionHandler(String actionId) {
-        mActionId = actionId;
-    }
-
-    @Override
-    public final void reportAvailableDirectActions(DirectActionReporter reporter) {
-        if (isAvailable()) reporter.addDirectAction(mActionId);
-    }
-
-    @Override
-    public final boolean performDirectAction(
-            String actionId, Bundle arguments, Callback<Bundle> callback) {
-        if (!mActionId.equals(actionId)) return false;
-
-        if (!isAvailable()) return false;
-
-        run();
-        callback.onResult(Bundle.EMPTY);
-        return true;
-    }
-
-    /** Returns {@code true} if the action is currently available. */
-    protected abstract boolean isAvailable();
-
-    /**
-     * Performs the action, if it is available.
-     *
-     * <p>{@link #isAvailable} is guaranteed to be called just before this method.
-     */
-    protected abstract void run();
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java
index 37737cc..d279550 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java
@@ -13,6 +13,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.util.DisplayMetrics;
@@ -100,7 +101,14 @@
             @NonNull HubLayoutDependencyHolder dependencyHolder) {
         super(context, updateHost, renderHost);
         mLayoutStateProvider = layoutStateProvider;
+        // This is the R.id.tab_switcher_view_holder. It is used by tablets for the tab switcher,
+        // but in that case it is the animated object and is opaque. Here we will animate the
+        // HubContainerView instead and just animate and just use this view as a transparent
+        // container for z-indexing and geometry.
+        // TODO(crbug/1499984): Consider removing the tab_switcher_view_holder post launch.
         mRootView = dependencyHolder.getHubRootView();
+        mRootView.setBackgroundColor(Color.TRANSPARENT);
+
         HubManager hubManager = dependencyHolder.getHubManager();
         mHubController = hubManager.getHubController();
         mPaneManager = hubManager.getPaneManager();
@@ -212,9 +220,11 @@
                     }
                 });
 
+        mRootView.setVisibility(View.VISIBLE);
         containerView.setVisibility(View.INVISIBLE);
         mRootView.addView(
                 containerView,
+                /* index= */ 0,
                 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
         containerView.runOnNextLayout(this::queueAnimation);
     }
@@ -290,8 +300,9 @@
     public void doneHiding() {
         super.doneHiding();
         HubContainerView containerView = mHubController.getContainerView();
-        mRootView.removeView(containerView);
         containerView.setVisibility(View.INVISIBLE);
+        mRootView.removeView(containerView);
+        mRootView.setVisibility(View.GONE);
         mCurrentAnimationRunner = null;
         mHubController.onHubLayoutDoneHiding();
 
@@ -318,8 +329,8 @@
 
     @Override
     public boolean onBackPressed() {
-        // TODO(crbug/1487209): Forward this to the HubManager. Legacy backpress handler soon to be
-        // obsolete.
+        // TODO(crbug/1487209): Forward this to the HubManager. This is for the legacy backpress
+        // handler which will soon be obsolete.
         return false;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayoutPublicTransitTest.java b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayoutPublicTransitTest.java
new file mode 100644
index 0000000..ce54872
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayoutPublicTransitTest.java
@@ -0,0 +1,49 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.hub;
+
+import static org.chromium.base.test.transit.TransitAsserts.assertFinalDestination;
+import static org.chromium.chrome.browser.flags.ChromeFeatureList.ANDROID_HUB;
+import static org.chromium.chrome.browser.flags.ChromeFeatureList.START_SURFACE_REFACTOR;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DoNotBatch;
+import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.chrome.test.transit.BasePageStation;
+import org.chromium.chrome.test.transit.ChromeTabbedActivityPublicTransitEntryPoints;
+import org.chromium.chrome.test.transit.HubStation;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
+
+/** Public transit instrumentation/integration test of Hub. */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@EnableFeatures({ANDROID_HUB, START_SURFACE_REFACTOR})
+// TODO(crbug/1498446): Add support for batching.
+@DoNotBatch(reason = "Public transit lacks batch support. Hub does not exit cleanly yet.")
+public class HubLayoutPublicTransitTest {
+    @Rule
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
+
+    ChromeTabbedActivityPublicTransitEntryPoints mTransitEntryPoints =
+            new ChromeTabbedActivityPublicTransitEntryPoints(mActivityTestRule);
+
+    @Test
+    @LargeTest
+    public void testEnterHub() {
+        BasePageStation page = mTransitEntryPoints.startOnBlankPage();
+
+        HubStation hubStation = page.openHub();
+
+        assertFinalDestination(hubStation);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubProviderUnitTest.java b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubProviderUnitTest.java
index 2a8c075..56f48e9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubProviderUnitTest.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubProviderUnitTest.java
@@ -22,6 +22,7 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import org.chromium.base.supplier.LazyOneshotSupplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.ui.base.TestActivity;
 
@@ -58,7 +59,7 @@
         assertNotNull(hubManagerSupplier);
         assertFalse(hubManagerSupplier.hasValue());
 
-        builder.registerPane(PaneId.TAB_SWITCHER, () -> mMockPane);
+        builder.registerPane(PaneId.TAB_SWITCHER, LazyOneshotSupplier.fromValue(mMockPane));
         assertFalse(builder.isBuilt());
 
         HubManager hubManager = hubManagerSupplier.get();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java
index 6f2d3fa..8dbfd8c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java
@@ -19,6 +19,7 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.ObserverList;
+import org.chromium.base.Promise;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
@@ -35,6 +36,10 @@
 import org.chromium.chrome.browser.signin.services.SigninManager;
 import org.chromium.chrome.browser.signin.services.SigninPreferencesManager;
 import org.chromium.components.externalauth.ExternalAuthUtils;
+import org.chromium.components.signin.AccountManagerFacade;
+import org.chromium.components.signin.AccountManagerFacadeProvider;
+import org.chromium.components.signin.AccountUtils;
+import org.chromium.components.signin.AccountsChangeObserver;
 import org.chromium.components.signin.base.CoreAccountId;
 import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.signin.identitymanager.AccountInfoServiceProvider;
@@ -56,15 +61,15 @@
 
 /**
  * Android wrapper of the SigninManager which provides access from the Java layer.
- * <p/>
- * This class handles common paths during the sign-in and sign-out flows.
- * <p/>
- * Only usable from the UI thread as the native SigninManager requires its access to be in the
- * UI thread.
- * <p/>
- * See chrome/browser/android/signin/signin_manager_android.h for more details.
+ *
+ * <p>This class handles common paths during the sign-in and sign-out flows.
+ *
+ * <p>Only usable from the UI thread as the native SigninManager requires its access to be in the UI
+ * thread.
+ *
+ * <p>See chrome/browser/android/signin/signin_manager_android.h for more details.
  */
-class SigninManagerImpl implements IdentityManager.Observer, SigninManager {
+class SigninManagerImpl implements IdentityManager.Observer, SigninManager, AccountsChangeObserver {
     private static final String TAG = "SigninManager";
     private static final int[] SYNC_DATA_TYPES = {BrowsingDataType.HISTORY, BrowsingDataType.CACHE,
             BrowsingDataType.COOKIES, BrowsingDataType.PASSWORDS, BrowsingDataType.FORM_DATA};
@@ -75,6 +80,7 @@
      */
     private long mNativeSigninManagerAndroid;
     private final AccountTrackerService mAccountTrackerService;
+    private final AccountManagerFacade mAccountManagerFacade;
     private final IdentityManager mIdentityManager;
     private final IdentityMutator mIdentityMutator;
     private final SyncService mSyncService;
@@ -117,8 +123,12 @@
         identityManager.addObserver(signinManager);
         AccountInfoServiceProvider.init(identityManager, accountTrackerService);
 
-        signinManager.reloadAllAccountsFromSystem(CoreAccountInfo.getIdFrom(
-                identityManager.getPrimaryAccountInfo(ConsentLevel.SIGNIN)));
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)) {
+            CoreAccountInfo primaryAccountInfo =
+                    identityManager.getPrimaryAccountInfo(ConsentLevel.SIGNIN);
+            signinManager.reloadAllAccountsFromSystem(
+                    CoreAccountInfo.getIdFrom(primaryAccountInfo));
+        }
         return signinManager;
     }
 
@@ -134,6 +144,17 @@
 
         mSigninAllowedByPolicy =
                 SigninManagerImplJni.get().isSigninAllowedByPolicy(mNativeSigninManagerAndroid);
+        mAccountManagerFacade = AccountManagerFacadeProvider.getInstance();
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)) {
+            mAccountManagerFacade.addObserver(this);
+            Promise<List<CoreAccountInfo>> coreAccountInfosPromise =
+                    mAccountManagerFacade.getCoreAccountInfos();
+            if (coreAccountInfosPromise.isFulfilled()) {
+                seedThenReloadAllAccountsFromSystem(
+                        CoreAccountInfo.getIdFrom(
+                                identityManager.getPrimaryAccountInfo(ConsentLevel.SIGNIN)));
+            }
+        }
     }
 
     /**
@@ -145,9 +166,26 @@
     void destroy() {
         AccountInfoServiceProvider.get().destroy();
         mIdentityManager.removeObserver(this);
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)) {
+            mAccountManagerFacade.removeObserver(this);
+        }
         mNativeSigninManagerAndroid = 0;
     }
 
+    /** Implements {@link AccountsChangeObserver}. */
+    @Override
+    public void onCoreAccountInfosChanged() {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)) {
+            throw new IllegalStateException(
+                    "This method should never be called when SeedAccountsRevamp is disabled");
+        }
+        Promise<List<CoreAccountInfo>> coreAccountInfosPromise =
+                mAccountManagerFacade.getCoreAccountInfos();
+        assert coreAccountInfosPromise.isFulfilled();
+        // TODO(crbug/1491005): Add the seeding logic here and move the primary account validation
+        // for the signin checker to here
+    }
+
     /**
      * Extracts the domain name of a given account's email.
      */
@@ -307,23 +345,53 @@
         mSignInState = signInState;
         signInState = null;
 
-        Log.i(TAG, "Signin starts (enabling sync: %b).", mSignInState.shouldTurnSyncOn());
-        AccountInfoServiceProvider.get()
-                .getAccountInfoByEmail(mSignInState.mAccount.name)
-                .then(accountInfo -> {
-                    mSignInState.mCoreAccountInfo = accountInfo;
-                    notifySignInAllowedChanged();
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)) {
+            // Retrieve the primary account and use it to seed and reload all accounts.
+            if (!mAccountManagerFacade.getCoreAccountInfos().isFulfilled()) {
+                throw new IllegalStateException(
+                        "Account information should be available on signin");
+            }
+            mSignInState.mCoreAccountInfo =
+                    AccountUtils.findCoreAccountInfoByEmail(
+                            mAccountManagerFacade.getCoreAccountInfos().getResult(),
+                            mSignInState.mAccount.name);
+            if (mSignInState.mCoreAccountInfo == null) {
+                throw new IllegalStateException(
+                        "The account should be on the device before it can be set as primary.");
+            }
+            seedThenReloadAllAccountsFromSystem(mSignInState.mCoreAccountInfo.getId());
+            notifySignInAllowedChanged();
 
-                    if (mSignInState.shouldTurnSyncOn()) {
-                        Log.d(TAG, "Checking if account has policy management enabled");
-                        fetchAndApplyCloudPolicy(mSignInState.mCoreAccountInfo,
-                                this::finishSignInAfterPolicyEnforced);
-                    } else {
-                        // Sign-in without sync doesn't enforce enterprise policy, so skip that
-                        // step.
-                        finishSignInAfterPolicyEnforced();
-                    }
-                });
+            if (mSignInState.shouldTurnSyncOn()) {
+                Log.d(TAG, "Checking if account has policy management enabled");
+                fetchAndApplyCloudPolicy(
+                        mSignInState.mCoreAccountInfo, this::finishSignInAfterPolicyEnforced);
+            } else {
+                // Sign-in without sync doesn't enforce enterprise policy, so skip that
+                // step.
+                finishSignInAfterPolicyEnforced();
+            }
+        } else {
+            Log.i(TAG, "Signin starts (enabling sync: %b).", mSignInState.shouldTurnSyncOn());
+            AccountInfoServiceProvider.get()
+                    .getAccountInfoByEmail(mSignInState.mAccount.name)
+                    .then(
+                            accountInfo -> {
+                                mSignInState.mCoreAccountInfo = accountInfo;
+                                notifySignInAllowedChanged();
+
+                                if (mSignInState.shouldTurnSyncOn()) {
+                                    Log.d(TAG, "Checking if account has policy management enabled");
+                                    fetchAndApplyCloudPolicy(
+                                            mSignInState.mCoreAccountInfo,
+                                            this::finishSignInAfterPolicyEnforced);
+                                } else {
+                                    // Sign-in without sync doesn't enforce enterprise policy, so
+                                    // skip that step.
+                                    finishSignInAfterPolicyEnforced();
+                                }
+                            });
+        }
     }
 
     /**
@@ -338,7 +406,9 @@
 
         // Setting the primary account triggers observers which query accounts from IdentityManager.
         // Reloading before setting the primary ensures they don't get an empty list of accounts.
-        reloadAllAccountsFromSystem(mSignInState.mCoreAccountInfo.getId());
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)) {
+            reloadAllAccountsFromSystem(mSignInState.mCoreAccountInfo.getId());
+        }
 
         @ConsentLevel
         int consentLevel =
@@ -520,6 +590,9 @@
 
         Log.d(TAG, "Signin flow aborted.");
         notifySignInAllowedChanged();
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)) {
+            seedThenReloadAllAccountsFromSystem(null);
+        }
     }
 
     @VisibleForTesting
@@ -537,6 +610,9 @@
                     0);
         }
         SignOutCallback signOutCallback = mSignOutState.mSignOutCallback;
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)) {
+            seedThenReloadAllAccountsFromSystem(null);
+        }
         mSignOutState = null;
 
         if (signOutCallback != null) signOutCallback.signOutComplete();
@@ -572,13 +648,25 @@
 
     @Override
     public void reloadAllAccountsFromSystem(@Nullable CoreAccountId primaryAccountId) {
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)) {
+            throw new IllegalStateException(
+                    "This method should never be called when SeedAccountsRevamp is enabled");
+        }
         mIdentityMutator.reloadAllAccountsFromSystemWithPrimaryAccount(primaryAccountId);
     }
 
-    /** Called when account seeding is complete. */
-    public void onAccountsSeeded(List<CoreAccountInfo> coreAccountInfos) {
-        // TODO(crbug/1491005): Call this right after seeding.
-        mIdentityManager.refreshAccountInfoIfStale(coreAccountInfos);
+    private void seedThenReloadAllAccountsFromSystem(@Nullable CoreAccountId primaryAccountId) {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)) {
+            throw new IllegalStateException(
+                    "This method should never be called when SeedAccountsRevamp is disabled");
+        }
+        if (!mAccountManagerFacade.getCoreAccountInfos().isFulfilled()) {
+            throw new IllegalStateException("Account information should be available when seeding");
+        }
+        mIdentityMutator.seedAccountsThenReloadAllAccountsWithPrimaryAccount(
+                mAccountManagerFacade.getCoreAccountInfos().getResult(), primaryAccountId);
+        mIdentityManager.refreshAccountInfoIfStale(
+                mAccountManagerFacade.getCoreAccountInfos().getResult());
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
index b477421e..10417a8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -12,7 +12,6 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.CancellationSignal;
 import android.os.Handler;
 import android.text.TextUtils;
 import android.view.View;
@@ -58,7 +57,6 @@
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
 import org.chromium.chrome.browser.crash.ChromePureJavaExceptionReporter;
 import org.chromium.chrome.browser.device_lock.DeviceLockActivityLauncherImpl;
-import org.chromium.chrome.browser.directactions.DirectActionInitializer;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.dom_distiller.ReaderModeToolbarButtonController;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
@@ -193,7 +191,6 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.function.BooleanSupplier;
-import java.util.function.Consumer;
 
 /**
  * The root UI coordinator. This class will eventually be responsible for inflating and managing
@@ -259,7 +256,6 @@
     private SnackbarManager mBottomSheetSnackbarManager;
 
     private ScrimCoordinator mScrimCoordinator;
-    private DirectActionInitializer mDirectActionInitializer;
     private List<ButtonDataProvider> mButtonDataProviders;
     @Nullable
     private AdaptiveToolbarButtonController mAdaptiveToolbarButtonController;
@@ -739,7 +735,6 @@
     @Override
     public void onPostInflationStartup() {
         initAppMenu();
-        initDirectActionInitializer();
         initBottomSheetObserver();
         initSnackbarObserver();
         initBrowserControlsObserver();
@@ -1101,35 +1096,6 @@
         }
     }
 
-    /**
-     * Performs a direct action.
-     *
-     * @param actionId Name of the direct action to perform.
-     * @param arguments Arguments for this action.
-     * @param cancellationSignal Signal used to cancel a direct action from the caller.
-     * @param callback Callback to run when the action is done.
-     */
-    public void onPerformDirectAction(String actionId, Bundle arguments,
-            CancellationSignal cancellationSignal, Consumer<Bundle> callback) {
-        if (mDirectActionInitializer == null) return;
-        mDirectActionInitializer.onPerformDirectAction(
-                actionId, arguments, cancellationSignal, callback);
-    }
-
-    /**
-     * Lists direct actions supported.
-     *
-     * Returns a list of direct actions supported by the Activity associated with this
-     * RootUiCoordinator.
-     *
-     * @param cancellationSignal Signal used to cancel a direct action from the caller.
-     * @param callback Callback to run when the action is done.
-     */
-    public void onGetDirectActions(CancellationSignal cancellationSignal, Consumer<List> callback) {
-        if (mDirectActionInitializer == null) return;
-        mDirectActionInitializer.onGetDirectActions(cancellationSignal, callback);
-    }
-
     // Protected class methods
     protected void onLayoutManagerAvailable(LayoutManagerImpl layoutManager) {
         mLayoutManager = layoutManager;
@@ -1656,13 +1622,6 @@
         return mBottomSheetSnackbarManager;
     }
 
-    private void initDirectActionInitializer() {
-        mDirectActionInitializer = new DirectActionInitializer(mActivityType,
-                mMenuOrKeyboardActionController, mActivity::onBackPressed,
-                mTabModelSelectorSupplier.get(), mFindToolbarManager);
-        mActivityLifecycleDispatcher.register(mDirectActionInitializer);
-    }
-
     /**
      * Initializes a glue logic that suppresses Contextual Search and hides the Page Zoom slider
      * while a Bottom Sheet feature is in action.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
index 347b1ba..4477a84 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
@@ -60,6 +60,7 @@
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.hub.HubLayoutDependencyHolder;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.layouts.LayoutStateProvider;
 import org.chromium.chrome.browser.layouts.LayoutTestUtils;
@@ -109,6 +110,8 @@
 
     @Mock private TabSwitcher mTabSwitcher;
 
+    @Mock private HubLayoutDependencyHolder mHubLayoutDependencyHolder;
+
     @Mock private TabSwitcher.TabListDelegate mTabListDelegate;
     @Mock private TabSwitcher.Controller mTabSwitcherController;
     @Mock private BrowserControlsStateProvider mBrowserControlsStateProvider;
@@ -256,7 +259,8 @@
                         () -> {
                             mTabSwitcherSupplier.set(mTabSwitcher);
                             return container;
-                        });
+                        },
+                        mHubLayoutDependencyHolder);
 
         setUpLayouts();
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java
deleted file mode 100644
index eb892e9..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java
+++ /dev/null
@@ -1,102 +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.chrome.browser.directactions;
-
-import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import android.os.Bundle;
-
-import androidx.test.filters.MediumTest;
-
-import org.hamcrest.Matchers;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.Batch;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabLaunchType;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Tests {@link CloseTabDirectActionHandler}. */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-@Batch(Batch.PER_CLASS)
-public class CloseTabDirectActionHandlerTest {
-    @ClassRule
-    public static ChromeTabbedActivityTestRule sActivityTestRule =
-            new ChromeTabbedActivityTestRule();
-
-    @Rule
-    public BlankCTATabInitialStateRule mBlankCTATabInitialStateRule =
-            new BlankCTATabInitialStateRule(sActivityTestRule, false);
-
-    private TabModelSelector mSelector;
-    private CloseTabDirectActionHandler mHandler;
-
-    @Before
-    public void setUp() throws Exception {
-        // Setup an activity with two blank tabs.
-        sActivityTestRule.loadUrlInNewTab(
-                "about:blank", /* incognito= */ false, TabLaunchType.FROM_CHROME_UI);
-
-        mSelector = sActivityTestRule.getActivity().getTabModelSelector();
-        mHandler = new CloseTabDirectActionHandler(mSelector);
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"DirectActions"})
-    public void testCloseTabs() {
-        // Actions are available
-        assertThat(getDirectActions(), Matchers.containsInAnyOrder("close_tab"));
-
-        // Close current tab
-        Tab initiallyCurrent = mSelector.getCurrentTab();
-        performAction("close_tab");
-        assertThat(
-                mSelector.getCurrentTab(), Matchers.not(Matchers.sameInstance(initiallyCurrent)));
-
-        assertEquals(1, mSelector.getTotalTabCount());
-        // Close last tab
-        performAction("close_tab");
-
-        // No tabs are left, so actions aren't available anymore.
-        assertThat(getDirectActions(), Matchers.empty());
-    }
-
-    private void performAction(String name) {
-        List<Bundle> responses = new ArrayList<>();
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    assertTrue(
-                            mHandler.performDirectAction(
-                                    name, Bundle.EMPTY, (r) -> responses.add(r)));
-                });
-        assertThat(responses, Matchers.hasSize(1));
-    }
-
-    private List<String> getDirectActions() {
-        FakeDirectActionReporter reporter = new FakeDirectActionReporter();
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> mHandler.reportAvailableDirectActions(reporter));
-        return reporter.getDirectActions();
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityCustomTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityCustomTabTest.java
deleted file mode 100644
index 323d20a2..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityCustomTabTest.java
+++ /dev/null
@@ -1,60 +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.chrome.browser.directactions;
-
-import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
-
-import android.content.Intent;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.filters.MediumTest;
-
-import org.hamcrest.Matchers;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.app.ChromeActivity;
-import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
-import org.chromium.chrome.browser.customtabs.CustomTabsIntentTestUtils;
-import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-
-/**
- * Tests the availability of core direct actions in different activities.
- *
- * <p>This tests both {@link DirectActionInitializer} and its integration with {@link
- * ChromeActivity} and its different subclasses.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-public class DirectActionAvailabilityCustomTabTest {
-    @Rule
-    public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
-
-    @Rule public DirectActionTestRule mDirectActionRule = new DirectActionTestRule();
-
-    @Test
-    @MediumTest
-    @Feature({"DirectActions"})
-    public void testCoreDirectActionInCustomTabActivity() throws Exception {
-        Intent intent =
-                CustomTabsIntentTestUtils.createMinimalCustomTabIntent(
-                        ApplicationProvider.getApplicationContext(), "about:blank");
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-
-        assertThat(
-                DirectActionTestUtils.setupActivityAndGetDirectAction(mCustomTabActivityTestRule),
-                Matchers.containsInAnyOrder(
-                        "go_back",
-                        "reload",
-                        "go_forward",
-                        "bookmark_this_page",
-                        "preferences",
-                        "find_in_page"));
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityTabbedTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityTabbedTest.java
deleted file mode 100644
index 3f513d2..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityTabbedTest.java
+++ /dev/null
@@ -1,66 +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.chrome.browser.directactions;
-
-import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
-
-import androidx.test.filters.MediumTest;
-
-import org.hamcrest.Matchers;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.app.ChromeActivity;
-import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.components.embedder_support.util.UrlConstants;
-
-/**
- * Tests the availability of core direct actions in different activities.
- *
- * <p>This tests both {@link DirectActionInitializer} and its integration with {@link
- * ChromeActivity} and its different subclasses.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-public class DirectActionAvailabilityTabbedTest {
-    @Rule
-    public ChromeTabbedActivityTestRule mTabbedActivityTestRule =
-            new ChromeTabbedActivityTestRule();
-
-    @Rule public DirectActionTestRule mDirectActionRule = new DirectActionTestRule();
-
-    @Before
-    public void setUp() throws Exception {
-        // Using OnBlank times out when waiting for NTP. Using UrlConstants.NTP_URL makes the test
-        // work.
-        mTabbedActivityTestRule.startMainActivityWithURL(UrlConstants.NTP_URL);
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"DirectActions"})
-    public void testCoreDirectActionInTabbedActivity() throws Exception {
-        assertThat(
-                DirectActionTestUtils.setupActivityAndGetDirectAction(mTabbedActivityTestRule),
-                Matchers.containsInAnyOrder(
-                        "go_back",
-                        "reload",
-                        "go_forward",
-                        "bookmark_this_page",
-                        "downloads",
-                        "preferences",
-                        "open_history",
-                        "help",
-                        "new_tab",
-                        "close_tab",
-                        "close_all_tabs"));
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityWebappTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityWebappTest.java
deleted file mode 100644
index 592a139..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityWebappTest.java
+++ /dev/null
@@ -1,46 +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.chrome.browser.directactions;
-
-import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
-
-import androidx.test.filters.MediumTest;
-
-import org.hamcrest.Matchers;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.app.ChromeActivity;
-import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.browser.webapps.WebappActivityTestRule;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-
-/**
- * Tests the availability of core direct actions in different activities.
- *
- * <p>This tests both {@link DirectActionInitializer} and its integration with {@link
- * ChromeActivity} and its different subclasses.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-public class DirectActionAvailabilityWebappTest {
-    @Rule public WebappActivityTestRule mWebAppActivityTestRule = new WebappActivityTestRule();
-
-    @Rule public DirectActionTestRule mDirectActionRule = new DirectActionTestRule();
-
-    @Test
-    @MediumTest
-    @Feature({"DirectActions"})
-    public void testCoreDirectActionInWebappActivity() throws Exception {
-        mWebAppActivityTestRule.startWebappActivity();
-
-        assertThat(
-                DirectActionTestUtils.setupActivityAndGetDirectAction(mWebAppActivityTestRule),
-                Matchers.containsInAnyOrder("go_back", "reload", "go_forward", "find_in_page"));
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestRule.java
deleted file mode 100644
index fbc5133..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestRule.java
+++ /dev/null
@@ -1,66 +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.chrome.browser.directactions;
-
-import androidx.annotation.Nullable;
-
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-import org.chromium.chrome.browser.AppHooks;
-import org.chromium.chrome.browser.AppHooksImpl;
-import org.chromium.chrome.test.ChromeActivityTestRule;
-
-import java.util.function.Consumer;
-
-/** Enables direct actions in an activity started by a {@link ChromeActivityTestRule}. */
-public class DirectActionTestRule implements TestRule {
-    /**
-     * A concrete implementation of DirectActionCoordinator, based on {@link
-     * FakeDirectActionReporter}.
-     */
-    private DirectActionCoordinator mCoordinator;
-
-    /** Returns the coordinator created by the rule. */
-    public @Nullable DirectActionCoordinator getCoordinator() {
-        return mCoordinator;
-    }
-
-    /** Disables direct action in the next activities that are started. */
-    public void disableDirectActions() {
-        // Since mCoordinator is null AppHooks will return null. Direct actions should not be
-        // available.
-        mCoordinator = null;
-    }
-
-    @Override
-    public Statement apply(Statement base, Description description) {
-        return new Statement() {
-            @Override
-            public void evaluate() throws Throwable {
-                mCoordinator =
-                        new DirectActionCoordinator() {
-                            @Override
-                            protected DirectActionReporter createReporter(Consumer callback) {
-                                return new FakeDirectActionReporter(callback);
-                            }
-                        };
-                AppHooks.setInstanceForTesting(
-                        new AppHooksImpl() {
-                            @Override
-                            public DirectActionCoordinator createDirectActionCoordinator() {
-                                return mCoordinator;
-                            }
-                        });
-                try {
-                    base.evaluate();
-                } finally {
-                    AppHooksImpl.setInstanceForTesting(null);
-                }
-            }
-        };
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestUtils.java
deleted file mode 100644
index 93c36a6..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionTestUtils.java
+++ /dev/null
@@ -1,99 +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.chrome.browser.directactions;
-
-import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
-
-import static org.junit.Assert.assertTrue;
-
-import android.os.Bundle;
-import android.os.CancellationSignal;
-
-import org.hamcrest.Matchers;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.browser.app.ChromeActivity;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
-import org.chromium.chrome.test.util.ChromeTabUtils;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Utilities for writing tests that check for or perform direct actions on an activity. */
-class DirectActionTestUtils {
-    /** Perform a direct action, with the given name. */
-    public static void callOnPerformDirectActions(
-            ChromeActivity activity, String actionId, Callback<Bundle> callback) {
-        // This method is not taking a Consumer to avoid issues with tests running against Android
-        // API < 24 not even being able to load the test class.
-
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    activity.onPerformDirectAction(
-                            actionId,
-                            Bundle.EMPTY,
-                            new CancellationSignal(),
-                            (r) -> callback.onResult((Bundle) r));
-                });
-    }
-
-    /** Gets the list of direct actions. */
-    public static List<String> callOnGetDirectActions(ChromeActivity activity) {
-        List<String> directActions = new ArrayList<>();
-
-        // onGetDirectActions reports a List<String> because that's what FakeDirectActionReporter
-        // creates.
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    activity.onGetDirectActions(
-                            new CancellationSignal(),
-                            (actions) -> directActions.addAll((List<String>) actions));
-                });
-        return directActions;
-    }
-
-    /**
-     * Sets the ChromeActivityTestRule by forcing "go_forward" to be available.
-     *
-     * <p>The activity of the given rule must have been started and have loaded a page.
-     */
-    static List<String> setupActivityAndGetDirectAction(ChromeActivityTestRule<?> rule)
-            throws Exception {
-        allowGoForward(rule);
-        return callOnGetDirectActions(rule.getActivity());
-    }
-
-    /**
-     * Forces availability of the "go_forward" direct action on the current tab by loading another
-     * URL then navigating back to the current one.
-     *
-     * <p>The activity of the given rule must have been started and have loaded a page.
-     */
-    static void allowGoForward(ChromeActivityTestRule<?> rule) throws Exception {
-        ChromeActivity activity = rule.getActivity();
-        String initialUrl =
-                TestThreadUtils.runOnUiThreadBlocking(
-                        () -> activity.getCurrentWebContents().getLastCommittedUrl().getSpec());
-
-        // Any built-in page that is not about:blank and is reasonably cheap to render will do,
-        // here.
-        Tab tab = activity.getTabModelSelector().getCurrentTab();
-        String visitedUrl = "chrome://version/";
-        assertThat(initialUrl, Matchers.not(Matchers.equalTo(visitedUrl)));
-        rule.loadUrl(visitedUrl);
-        ChromeTabUtils.waitForTabPageLoaded(tab, visitedUrl);
-
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> activity.getCurrentWebContents().getNavigationController().goBack());
-        ChromeTabUtils.waitForTabPageLoaded(tab, initialUrl);
-        assertTrue(tab.canGoForward());
-    }
-
-    private DirectActionTestUtils() {
-        // This is a utility class; it is not meant to be instantiated.
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionsInActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionsInActivityTest.java
deleted file mode 100644
index fbb4bf57..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionsInActivityTest.java
+++ /dev/null
@@ -1,150 +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.chrome.browser.directactions;
-
-import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.fail;
-
-import android.os.Bundle;
-
-import androidx.test.filters.MediumTest;
-
-import org.hamcrest.Matchers;
-import org.junit.After;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.Callback;
-import org.chromium.base.test.util.Batch;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.HistogramWatcher;
-import org.chromium.base.test.util.UserActionTester;
-import org.chromium.chrome.browser.app.ChromeActivity;
-import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-
-/**
- * Tests the implementation of {@link ChromeActivity#onGetDirectActions} and {@link
- * ChromeActivity#onPerformDirectAction} and its integration with the {@link
- * DirectActionCoordinator}.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-@Batch(Batch.PER_CLASS)
-public class DirectActionsInActivityTest {
-    @Rule
-    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
-
-    @Rule public DirectActionTestRule mDirectActionRule = new DirectActionTestRule();
-
-    private UserActionTester mActionTester;
-
-    private ChromeActivity getActivity() {
-        return mActivityTestRule.getActivity();
-    }
-
-    @After
-    public void tearDown() {
-        if (mActionTester != null) mActionTester.tearDown();
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"DirectActions"})
-    public void testDirectActionsDisabled() throws Exception {
-        // disableDirectActions() makes AppHooks.createDirectActionCoordinator return null. This
-        // should mean that direct actions are not available.
-        mDirectActionRule.disableDirectActions();
-
-        mActivityTestRule.startMainActivityOnBlankPage();
-
-        assertThat(DirectActionTestUtils.callOnGetDirectActions(getActivity()), Matchers.empty());
-
-        Bundle result = new Bundle();
-        DirectActionTestUtils.callOnPerformDirectActions(
-                getActivity(), "test", (r) -> result.putAll((Bundle) r));
-
-        // Direct comparison with Bundle.EMPTY does not work.
-        assertThat(result.keySet().isEmpty(), is(true));
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"DirectActions"})
-    public void testCallDirectAction() throws Exception {
-        mActivityTestRule.startMainActivityOnBlankPage();
-
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    // Register a single direct action called "test"
-                    mDirectActionRule
-                            .getCoordinator()
-                            .register(
-                                    new DirectActionHandler() {
-                                        @Override
-                                        public void reportAvailableDirectActions(
-                                                DirectActionReporter reporter) {
-                                            reporter.addDirectAction("test");
-                                        }
-
-                                        @Override
-                                        public boolean performDirectAction(
-                                                String actionId,
-                                                Bundle arguments,
-                                                Callback<Bundle> callback) {
-                                            if (!"test".equals(actionId)) return false;
-
-                                            Bundle bundle = new Bundle();
-                                            bundle.putBoolean("ran_test", true);
-                                            callback.onResult(bundle);
-                                            return true;
-                                        }
-                                    });
-                });
-
-        mActionTester = new UserActionTester();
-
-        assertThat(
-                DirectActionTestUtils.callOnGetDirectActions(getActivity()),
-                Matchers.hasItem("test"));
-        assertThat(mActionTester.getActions(), Matchers.hasItem("Android.DirectAction.List"));
-
-        var histogramWatcher =
-                HistogramWatcher.newSingleRecordWatcher(
-                        "Android.DirectAction.Perform",
-                        DirectActionUsageHistogram.DirectActionId.UNKNOWN);
-        DirectActionTestUtils.callOnPerformDirectActions(
-                getActivity(), "doesnotexist", (r) -> fail("Unexpected result: " + r));
-        histogramWatcher.assertExpected();
-
-        histogramWatcher =
-                HistogramWatcher.newSingleRecordWatcher(
-                        "Android.DirectAction.Perform",
-                        DirectActionUsageHistogram.DirectActionId.OTHER);
-        Bundle result = new Bundle();
-        DirectActionTestUtils.callOnPerformDirectActions(
-                getActivity(), "test", (r) -> result.putAll((Bundle) r));
-        assertThat(result.keySet(), Matchers.contains("ran_test"));
-        histogramWatcher.assertExpected();
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"DirectActions"})
-    public void testDirectActionsDisabledInIncognitoMode() throws Exception {
-        mActivityTestRule.startMainActivityOnBlankPage();
-        mActivityTestRule.loadUrlInNewTab("about:blank", /* incognito= */ true);
-
-        assertThat(DirectActionTestUtils.callOnGetDirectActions(getActivity()), Matchers.empty());
-        DirectActionTestUtils.callOnPerformDirectActions(
-                getActivity(), "help", (r) -> fail("Unexpected result: " + r));
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/FakeDirectActionReporter.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/FakeDirectActionReporter.java
deleted file mode 100644
index 74ea6067..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/FakeDirectActionReporter.java
+++ /dev/null
@@ -1,105 +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.chrome.browser.directactions;
-
-import androidx.annotation.RequiresApi;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-/**
- * Implementation of {@link DirectActionReporter} suitable for tests.
- *
- * <p>While Direct Actions are only available since Android Q, this test avoids using any type that
- * is specific to Android Q, so can run on older versions of the API. TODO(crbug.com/973781): Once
- * Chromium is built against Android Q SDK, have the test use {@code android.app.DirectAction}
- * directly.
- */
-@RequiresApi(24) // for java.util.function.Consumer.
-public class FakeDirectActionReporter implements DirectActionReporter {
-    /** List of action definitions available to tests. */
-    public final List<FakeDefinition> mActions = new ArrayList<>();
-
-    private final Consumer<List<String>> mCallback;
-    private final List<String> mDirectActions = new ArrayList<>();
-
-    public FakeDirectActionReporter() {
-        this(null);
-        // When using this constructor, actions can only be accessed using getDirectActions()
-    }
-
-    public FakeDirectActionReporter(Consumer<List<String>> callback) {
-        mCallback = callback;
-    }
-
-    public List<String> getDirectActions() {
-        return mDirectActions;
-    }
-
-    @Override
-    public void report() {
-        mCallback.accept(mDirectActions);
-    }
-
-    @Override
-    public DirectActionReporter.Definition addDirectAction(String actionId) {
-        FakeDefinition action = new FakeDefinition(actionId);
-        mActions.add(action);
-        mDirectActions.add(actionId);
-        return action;
-    }
-
-    /**
-     * A simple action definition for testing.
-     *
-     * <p>TODO(crbug.com/806868): Share these fakes. There is another one in
-     * chrome/android/junit/...directactions/
-     */
-    public static class FakeDefinition implements Definition {
-        /** Action name string. */
-        public final String mId;
-
-        /** Parameter list for this action definition. */
-        public List<FakeParameter> mParameters = new ArrayList<>();
-
-        /** Result list for this action definition. */
-        public List<FakeParameter> mResults = new ArrayList<>();
-
-        FakeDefinition(String id) {
-            mId = id;
-        }
-
-        @Override
-        public Definition withParameter(String name, @Type int type, boolean required) {
-            mParameters.add(new FakeParameter(name, type, required));
-            return this;
-        }
-
-        @Override
-        public Definition withResult(String name, @Type int type) {
-            mResults.add(new FakeParameter(name, type, true));
-            return this;
-        }
-    }
-
-    /** A simple parameter definition for testing. */
-    public static class FakeParameter {
-        /** Pamater name string. */
-        public final String mName;
-
-        /** Parameter type. */
-        @Type public final int mType;
-
-        /** Whether the parameter is required or not. */
-        public final boolean mRequired;
-
-        FakeParameter(String name, @Type int type, boolean required) {
-            mName = name;
-            mType = type;
-            mRequired = required;
-        }
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/MenuDirectActionHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/MenuDirectActionHandlerTest.java
deleted file mode 100644
index cbc81d9..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/MenuDirectActionHandlerTest.java
+++ /dev/null
@@ -1,164 +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.chrome.browser.directactions;
-
-import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.os.Bundle;
-
-import androidx.test.filters.MediumTest;
-import androidx.test.filters.SmallTest;
-
-import org.hamcrest.Matchers;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.Batch;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Criteria;
-import org.chromium.base.test.util.CriteriaHelper;
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.app.ChromeActivity;
-import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.chrome.test.R;
-import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Tests the integration of {@link MenuDirectActionHandler} with {@link ChromeActivity}. */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-@Batch(Batch.PER_CLASS)
-public class MenuDirectActionHandlerTest {
-    @ClassRule
-    public static ChromeTabbedActivityTestRule sActivityTestRule =
-            new ChromeTabbedActivityTestRule();
-
-    @Rule
-    public BlankCTATabInitialStateRule mBlankCTATabInitialStateRule =
-            new BlankCTATabInitialStateRule(sActivityTestRule, false);
-
-    private MenuDirectActionHandler mHandler;
-    private ChromeActivity mActivity;
-    private TabModelSelector mTabModelSelector;
-
-    @Before
-    public void setUp() throws Exception {
-        mActivity = sActivityTestRule.getActivity();
-        mTabModelSelector = mActivity.getTabModelSelector();
-        mHandler = new MenuDirectActionHandler(mActivity, mTabModelSelector);
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"DirectActions"})
-    public void testPerformDirectActionThroughActivity() {
-        mHandler.allowAllActions();
-
-        List<Bundle> results = new ArrayList<>();
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    assertTrue(
-                            mHandler.performDirectAction(
-                                    "new_tab", Bundle.EMPTY, (r) -> results.add(r)));
-                });
-        assertThat(results, Matchers.hasSize(1));
-        assertEquals(2, mTabModelSelector.getTotalTabCount());
-
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    assertFalse(
-                            mHandler.performDirectAction(
-                                    "doesnotexist",
-                                    Bundle.EMPTY,
-                                    (r) -> fail("Unexpected result: " + r)));
-                });
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"DirectActions"})
-    public void testReportAvailableActions() {
-        mHandler.allowAllActions();
-
-        assertThat(
-                getDirectActions(),
-                Matchers.containsInAnyOrder(
-                        "bookmark_this_page",
-                        "reload",
-                        "downloads",
-                        "help",
-                        "new_tab",
-                        "open_history",
-                        "preferences",
-                        "close_all_tabs"));
-
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    mTabModelSelector.closeAllTabs();
-                });
-        // Wait for any pending animations for tab closures to complete.
-        CriteriaHelper.pollUiThread(
-                () -> Criteria.checkThat(mTabModelSelector.getTotalTabCount(), Matchers.is(0)));
-        assertThat(
-                getDirectActions(),
-                Matchers.containsInAnyOrder("downloads", "help", "new_tab", "preferences"));
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"DirectActions"})
-    public void testRestrictAvailableActions() {
-        // By default, MenuDirectActionHandler supports no actions.
-        assertThat(getDirectActions(), Matchers.empty());
-
-        // Allow new_tab, then downloads
-        mHandler.allowlistActions(R.id.new_tab_menu_id);
-
-        assertThat(getDirectActions(), Matchers.contains("new_tab"));
-
-        mHandler.allowlistActions(R.id.downloads_menu_id);
-        assertThat(getDirectActions(), Matchers.containsInAnyOrder("new_tab", "downloads"));
-
-        // Other actions cannot be called.
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    assertFalse(
-                            mHandler.performDirectAction(
-                                    "help", Bundle.EMPTY, (r) -> fail("Unexpected result: " + r)));
-                });
-
-        // Allow all actions. This allows "help", never allowlisted explicitly
-        mHandler.allowAllActions();
-        assertThat(getDirectActions(), Matchers.hasItem("help"));
-
-        // Allowlisting extra actions is ignored and does not hide the other actions.
-        mHandler.allowlistActions(R.id.new_tab_menu_id);
-
-        assertThat(getDirectActions(), Matchers.hasItem("help"));
-    }
-
-    private List<String> getDirectActions() {
-        FakeDirectActionReporter reporter = new FakeDirectActionReporter();
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    mHandler.reportAvailableDirectActions(reporter);
-                });
-        return reporter.getDirectActions();
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/OWNERS
deleted file mode 100644
index ed6d5f0..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://components/autofill_assistant/OWNERS
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/directactions/FindInPageDirectActionHandlerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/directactions/FindInPageDirectActionHandlerTest.java
deleted file mode 100644
index afc47fd..0000000
--- a/chrome/android/junit/src/org/chromium/chrome/browser/directactions/FindInPageDirectActionHandlerTest.java
+++ /dev/null
@@ -1,148 +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.chrome.browser.directactions;
-
-import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.os.Bundle;
-
-import androidx.appcompat.widget.AppCompatEditText;
-import androidx.test.filters.SmallTest;
-
-import org.hamcrest.Matchers;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-import org.robolectric.annotation.Config;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.chrome.browser.directactions.DirectActionReporter.Definition;
-import org.chromium.chrome.browser.directactions.DirectActionReporter.Type;
-import org.chromium.chrome.browser.findinpage.FindToolbarManager;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-import org.chromium.content_public.browser.WebContents;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Tests {@link FindInPageDirectActionHandler}. */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class FindInPageDirectActionHandlerTest {
-    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
-
-    @Mock private DirectActionReporter mMockedReporter;
-
-    @Mock private AppCompatEditText mMockedEditText;
-
-    @Mock private WebContents mWebContents;
-
-    @Mock private FindToolbarManager mMockedFindToolbarManager;
-
-    private DirectActionHandler mHandler;
-
-    @Before
-    public void setUp() {
-        Tab mockTab = mock(Tab.class);
-        when(mockTab.isNativePage()).thenReturn(false);
-        when(mockTab.getWebContents()).thenReturn(mWebContents);
-
-        TabModelSelector mockTabModelSelector = mock(TabModelSelector.class);
-        when(mockTabModelSelector.getCurrentTab()).thenReturn(mockTab);
-
-        when(mMockedReporter.addDirectAction(org.mockito.ArgumentMatchers.anyString()))
-                .thenReturn(new FakeDirectActionDefinition("unused"));
-        mHandler =
-                new FindInPageDirectActionHandler(mockTabModelSelector, mMockedFindToolbarManager);
-        mHandler.reportAvailableDirectActions(mMockedReporter);
-        verify(mMockedReporter).addDirectAction("find_in_page");
-    }
-
-    @Test
-    @SmallTest
-    public void testWrongActionIdNotHandled() {
-        assertFalse(mHandler.performDirectAction("wrong_name", Bundle.EMPTY, null));
-        verify(mMockedFindToolbarManager, never()).showToolbar();
-    }
-
-    @Test
-    @SmallTest
-    public void testEmptyStringIgnored() {
-        List<Bundle> responses = new ArrayList<>();
-        assertTrue(
-                mHandler.performDirectAction(
-                        "find_in_page", Bundle.EMPTY, (response) -> responses.add(response)));
-        assertThat(responses, Matchers.hasSize(1));
-        // We still want to bring up the find toolbar.
-        verify(mMockedFindToolbarManager).showToolbar();
-        // Setting the search string should not happen.
-        verify(mMockedFindToolbarManager, never()).setFindQuery(anyString());
-    }
-
-    @Test
-    @SmallTest
-    public void testFindInPageFull() {
-        List<Bundle> responses = new ArrayList<>();
-        Bundle args = new Bundle();
-        args.putString("SEARCH_QUERY", "search string");
-        assertTrue(
-                mHandler.performDirectAction(
-                        "find_in_page", args, (response) -> responses.add(response)));
-        assertThat(responses, Matchers.hasSize(1));
-
-        verify(mMockedFindToolbarManager).showToolbar();
-        verify(mMockedFindToolbarManager).setFindQuery("search string");
-    }
-
-    /** A simple action definition for testing. */
-    private static class FakeDirectActionDefinition implements Definition {
-        final String mId;
-        List<FakeParameter> mParameters = new ArrayList<>();
-        List<FakeParameter> mResults = new ArrayList<>();
-
-        FakeDirectActionDefinition(String id) {
-            mId = id;
-        }
-
-        @Override
-        public Definition withParameter(String name, @Type int type, boolean required) {
-            mParameters.add(new FakeParameter(name, type, required));
-            return this;
-        }
-
-        @Override
-        public Definition withResult(String name, @Type int type) {
-            mResults.add(new FakeParameter(name, type, true));
-            return this;
-        }
-    }
-
-    /** A simple parameter definition for testing. */
-    private static class FakeParameter {
-        final String mName;
-
-        @Type final int mType;
-        final boolean mRequired;
-
-        FakeParameter(String name, @Type int type, boolean required) {
-            mName = name;
-            mType = type;
-            mRequired = required;
-        }
-    }
-}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/directactions/GoBackDirectActionHandlerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/directactions/GoBackDirectActionHandlerTest.java
deleted file mode 100644
index 557cdf1..0000000
--- a/chrome/android/junit/src/org/chromium/chrome/browser/directactions/GoBackDirectActionHandlerTest.java
+++ /dev/null
@@ -1,56 +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.chrome.browser.directactions;
-
-import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
-
-import static org.junit.Assert.assertTrue;
-
-import android.os.Bundle;
-
-import androidx.test.filters.SmallTest;
-
-import org.hamcrest.Matchers;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-import org.robolectric.annotation.Config;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Tests {@link GoBackDirectActionHandler}. */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class GoBackDirectActionHandlerTest {
-    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
-
-    @Mock private Runnable mAction;
-
-    @Mock private DirectActionReporter mReporter;
-
-    @Test
-    @SmallTest
-    public void testGoBack() {
-        DirectActionHandler handler = new GoBackDirectActionHandler(mAction);
-
-        handler.reportAvailableDirectActions(mReporter);
-        Mockito.verify(mReporter).addDirectAction("go_back");
-
-        List<Bundle> responses = new ArrayList<>();
-        assertTrue(
-                handler.performDirectAction(
-                        "go_back", Bundle.EMPTY, (response) -> responses.add(response)));
-
-        assertThat(responses, Matchers.hasSize(1));
-        Mockito.verify(mAction).run();
-    }
-}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerImplTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerImplTest.java
index d5a07af..61c9e41c 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerImplTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerImplTest.java
@@ -19,6 +19,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.accounts.Account;
 import android.content.Context;
 import android.os.UserManager;
 
@@ -73,6 +74,7 @@
 import org.chromium.components.sync.UserSelectableType;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -91,10 +93,10 @@
                     "given name",
                     null,
                     new AccountCapabilities(new HashMap<>()));
-    private static final CoreAccountInfo CHILD_CORE_ACCOUNT_INFO =
-            CoreAccountInfo.createFromEmailAndGaiaId(
-                    FakeAccountManagerFacade.generateChildEmail("user@domain.com"),
-                    "child-gaia-id-user");
+    // TODO(crbug/1491005): Add an addAccount overload to FakeAccountManagerFacade that takes a
+    // CoreAccountInfo as parameter and remove this field.
+    private static final Account ACCOUNT_FROM_INFO =
+            AccountUtils.createAccountFromName(ACCOUNT_INFO.getEmail());
 
     @Rule public final TestRule mFeaturesProcessorRule = new Features.JUnitProcessor();
 
@@ -144,6 +146,10 @@
 
         AccountManagerFacadeProvider.setInstanceForTests(mFakeAccountManagerFacade);
 
+        // TODO(crbug/1491005): Verify the first call to
+        // seedAccountsThenReloadAllAccountsWithPrimaryAccount that is made on creation of the
+        // SigninManager when the SeedAccountsRevamp flag is enabled. This can be done by creating
+        // the SigninManager in the test method directly.
         mSigninManager =
                 (SigninManagerImpl)
                         SigninManagerImpl.create(
@@ -163,6 +169,7 @@
     }
 
     @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signinAndTurnSyncOn() {
         when(mIdentityMutator.setPrimaryAccount(any(), anyInt(), anyInt()))
                 .thenReturn(PrimaryAccountError.NO_ERROR);
@@ -208,6 +215,61 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void signinAndTurnSyncOn_seedAccountsRevampEnabled() {
+        mFakeAccountManagerFacade.addAccount(ACCOUNT_FROM_INFO);
+        when(mIdentityMutator.setPrimaryAccount(any(), anyInt(), anyInt()))
+                .thenReturn(PrimaryAccountError.NO_ERROR);
+        when(mSyncService.getSelectedTypes()).thenReturn(Set.of(UserSelectableType.BOOKMARKS));
+
+        // There is no signed in account. Sign in is allowed.
+        assertTrue(mSigninManager.isSigninAllowed());
+        assertTrue(mSigninManager.isSyncOptInAllowed());
+        // Sign out is not allowed.
+        assertFalse(mSigninManager.isSignOutAllowed());
+
+        SigninManager.SignInCallback callback = mock(SigninManager.SignInCallback.class);
+        mSigninManager.signinAndEnableSync(
+                ACCOUNT_FROM_INFO, SigninAccessPoint.START_PAGE, callback);
+
+        List<CoreAccountInfo> coreAccountInfos =
+                mFakeAccountManagerFacade.getCoreAccountInfos().getResult();
+        CoreAccountInfo primaryAccountInfo =
+                AccountUtils.findCoreAccountInfoByEmail(coreAccountInfos, ACCOUNT_INFO.getEmail());
+        verify(mNativeMock)
+                .fetchAndApplyCloudPolicy(eq(NATIVE_SIGNIN_MANAGER), eq(primaryAccountInfo), any());
+        // A sign in operation is in progress, so we do not allow a new sign in/out operation.
+        assertFalse(mSigninManager.isSigninAllowed());
+        assertFalse(mSigninManager.isSyncOptInAllowed());
+        assertFalse(mSigninManager.isSignOutAllowed());
+
+        mSigninManager.finishSignInAfterPolicyEnforced();
+        verify(mIdentityMutator)
+                .seedAccountsThenReloadAllAccountsWithPrimaryAccount(
+                        coreAccountInfos, primaryAccountInfo.getId());
+        verify(mIdentityMutator)
+                .setPrimaryAccount(
+                        primaryAccountInfo.getId(),
+                        ConsentLevel.SYNC,
+                        SigninAccessPoint.START_PAGE);
+        verify(mSyncService).setSyncRequested();
+        // Signin should be complete and callback should be invoked.
+        verify(callback).onSignInComplete();
+        verify(callback, never()).onSignInAborted();
+
+        // The primary account is now present and consented to sign in and sync.  We do not allow
+        // another account to be signed in.
+        when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                        eq(NATIVE_IDENTITY_MANAGER), anyInt()))
+                .thenReturn(ACCOUNT_INFO);
+        assertFalse(mSigninManager.isSigninAllowed());
+        assertFalse(mSigninManager.isSyncOptInAllowed());
+        // Signing out is allowed.
+        assertTrue(mSigninManager.isSignOutAllowed());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signinNoTurnSyncOn() {
         when(mIdentityMutator.setPrimaryAccount(any(), anyInt(), anyInt()))
                 .thenReturn(PrimaryAccountError.NO_ERROR);
@@ -228,7 +290,7 @@
                         ACCOUNT_INFO.getId(), ConsentLevel.SIGNIN, SigninAccessPoint.START_PAGE);
 
         verify(mSyncService, never()).setSyncRequested();
-        // Signin should be complete qand callback should be invoked.
+        // Signin should be complete and callback should be invoked.
         verify(callback).onSignInComplete();
         verify(callback, never()).onSignInAborted();
 
@@ -241,6 +303,48 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void signinNoTurnSyncOn_seedAccountsRevampEnabled() {
+        mFakeAccountManagerFacade.addAccount(ACCOUNT_FROM_INFO);
+        when(mIdentityMutator.setPrimaryAccount(any(), anyInt(), anyInt()))
+                .thenReturn(PrimaryAccountError.NO_ERROR);
+
+        assertTrue(mSigninManager.isSigninAllowed());
+        assertTrue(mSigninManager.isSyncOptInAllowed());
+
+        SigninManager.SignInCallback callback = mock(SigninManager.SignInCallback.class);
+        mSigninManager.signin(ACCOUNT_FROM_INFO, SigninAccessPoint.START_PAGE, callback);
+
+        // Signin without turning on sync shouldn't apply policies.
+        verify(mNativeMock, never()).fetchAndApplyCloudPolicy(anyLong(), any(), any());
+
+        List<CoreAccountInfo> coreAccountInfos =
+                mFakeAccountManagerFacade.getCoreAccountInfos().getResult();
+        CoreAccountId primaryAccountId =
+                AccountUtils.findCoreAccountInfoByEmail(coreAccountInfos, ACCOUNT_INFO.getEmail())
+                        .getId();
+        verify(mIdentityMutator)
+                .seedAccountsThenReloadAllAccountsWithPrimaryAccount(
+                        coreAccountInfos, primaryAccountId);
+        verify(mIdentityMutator)
+                .setPrimaryAccount(
+                        primaryAccountId, ConsentLevel.SIGNIN, SigninAccessPoint.START_PAGE);
+
+        verify(mSyncService, never()).setSyncRequested();
+        // Signin should be complete and callback should be invoked.
+        verify(callback).onSignInComplete();
+        verify(callback, never()).onSignInAborted();
+
+        // The primary account is now present and consented to sign in.
+        when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                        eq(NATIVE_IDENTITY_MANAGER), eq(ConsentLevel.SIGNIN)))
+                .thenReturn(ACCOUNT_INFO);
+        assertFalse(mSigninManager.isSigninAllowed());
+        assertTrue(mSigninManager.isSyncOptInAllowed());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signOutNonSyncingAccountFromJavaWithManagedDomain() {
         when(mNativeMock.getManagementDomain(NATIVE_SIGNIN_MANAGER)).thenReturn("TestDomain");
 
@@ -258,6 +362,27 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void signOutNonSyncingAccountFromJavaWithManagedDomain_seedAccountsRevampEnabled() {
+        when(mNativeMock.getManagementDomain(NATIVE_SIGNIN_MANAGER)).thenReturn("TestDomain");
+
+        // Trigger the sign out flow!
+        mSigninManager.signOut(SignoutReason.TEST);
+
+        // The primary account should be cleared *before* clearing any account data.
+        // For more information see crbug.com/589028.
+        InOrder inOrder = inOrder(mNativeMock, mIdentityMutator);
+        inOrder.verify(mIdentityMutator).clearPrimaryAccount(eq(SignoutReason.TEST), anyInt());
+        verify(mIdentityMutator)
+                .seedAccountsThenReloadAllAccountsWithPrimaryAccount(List.of(), null);
+
+        // Sign-out should only clear the profile when the user is managed.
+        inOrder.verify(mNativeMock).wipeProfileData(eq(NATIVE_SIGNIN_MANAGER), any());
+        verify(mNativeMock, never()).wipeGoogleServiceWorkerCaches(anyLong(), any());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signOutSyncingAccountFromJavaWithManagedDomain() {
         when(mNativeMock.getManagementDomain(NATIVE_SIGNIN_MANAGER)).thenReturn("TestDomain");
 
@@ -275,6 +400,27 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void signOutSyncingAccountFromJavaWithManagedDomain_seedAccountsRevampEnabled() {
+        when(mNativeMock.getManagementDomain(NATIVE_SIGNIN_MANAGER)).thenReturn("TestDomain");
+
+        // Trigger the sign out flow!
+        mSigninManager.signOut(SignoutReason.TEST);
+
+        // The primary account should be cleared *before* clearing any account data.
+        // For more information see crbug.com/589028.
+        InOrder inOrder = inOrder(mNativeMock, mIdentityMutator);
+        inOrder.verify(mIdentityMutator).clearPrimaryAccount(eq(SignoutReason.TEST), anyInt());
+        verify(mIdentityMutator)
+                .seedAccountsThenReloadAllAccountsWithPrimaryAccount(List.of(), null);
+
+        // Sign-out should only clear the profile when the user is managed.
+        inOrder.verify(mNativeMock).wipeProfileData(eq(NATIVE_SIGNIN_MANAGER), any());
+        verify(mNativeMock, never()).wipeGoogleServiceWorkerCaches(anyLong(), any());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signOutNonSyncingAccountFromJavaWithNullDomain() {
         mSigninManager.signOut(SignoutReason.TEST);
 
@@ -290,6 +436,25 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void signOutNonSyncingAccountFromJavaWithNullDomain_seedAccountsRevampEnabled() {
+        mSigninManager.signOut(SignoutReason.TEST);
+
+        // The primary account should be cleared *before* clearing any account data.
+        // For more information see crbug.com/589028.
+        InOrder inOrder = inOrder(mNativeMock, mIdentityMutator);
+        inOrder.verify(mIdentityMutator).clearPrimaryAccount(eq(SignoutReason.TEST), anyInt());
+        verify(mIdentityMutator)
+                .seedAccountsThenReloadAllAccountsWithPrimaryAccount(List.of(), null);
+
+        // Sign-out should only clear the service worker cache when the user is neither managed or
+        // syncing.
+        verify(mNativeMock, never()).wipeProfileData(anyLong(), any());
+        inOrder.verify(mNativeMock).wipeGoogleServiceWorkerCaches(eq(NATIVE_SIGNIN_MANAGER), any());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signOutSyncingAccountFromJavaWithNullDomain() {
         // Simulate sign-out with non-managed account.
         when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
@@ -310,6 +475,30 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void signOutSyncingAccountFromJavaWithNullDomain_seedAccountsRevampEnabled() {
+        // Simulate sign-out with non-managed account.
+        when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                        eq(NATIVE_IDENTITY_MANAGER), anyInt()))
+                .thenReturn(ACCOUNT_INFO);
+
+        mSigninManager.signOut(SignoutReason.TEST);
+
+        // The primary account should be cleared *before* clearing any account data.
+        // For more information see crbug.com/589028.
+        InOrder inOrder = inOrder(mNativeMock, mIdentityMutator);
+        inOrder.verify(mIdentityMutator).clearPrimaryAccount(eq(SignoutReason.TEST), anyInt());
+        verify(mIdentityMutator)
+                .seedAccountsThenReloadAllAccountsWithPrimaryAccount(List.of(), null);
+
+        // Sign-out should only clear the service worker cache when the user has decided not to
+        // wipe data.
+        verify(mNativeMock, never()).wipeProfileData(anyLong(), any());
+        inOrder.verify(mNativeMock).wipeGoogleServiceWorkerCaches(eq(NATIVE_SIGNIN_MANAGER), any());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     @EnableFeatures(ChromeFeatureList.SYNC_ANDROID_LIMIT_NTP_PROMO_IMPRESSIONS)
     public void syncPromoShowCountResetWhenSignOutSyncingAccount() {
         ChromeSharedPreferences.getInstance()
@@ -340,6 +529,40 @@
     }
 
     @Test
+    @EnableFeatures({
+        ChromeFeatureList.SYNC_ANDROID_LIMIT_NTP_PROMO_IMPRESSIONS,
+        ChromeFeatureList.SEED_ACCOUNTS_REVAMP
+    })
+    public void syncPromoShowCountResetWhenSignOutSyncingAccount_seedAccountsRevampEnabled() {
+        ChromeSharedPreferences.getInstance()
+                .writeInt(
+                        ChromePreferenceKeys.SYNC_PROMO_SHOW_COUNT.createKey(
+                                SigninPreferencesManager.SyncPromoAccessPointId.NTP),
+                        1);
+
+        // Simulate sign-out with non-managed account.
+        when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                        eq(NATIVE_IDENTITY_MANAGER), anyInt()))
+                .thenReturn(ACCOUNT_INFO);
+
+        mSigninManager.signOut(SignoutReason.TEST);
+
+        ArgumentCaptor<Runnable> callback = ArgumentCaptor.forClass(Runnable.class);
+        verify(mNativeMock)
+                .wipeGoogleServiceWorkerCaches(eq(NATIVE_SIGNIN_MANAGER), callback.capture());
+        assertNotNull(callback.getValue());
+
+        callback.getValue().run();
+        assertEquals(
+                0,
+                ChromeSharedPreferences.getInstance()
+                        .readInt(
+                                ChromePreferenceKeys.SYNC_PROMO_SHOW_COUNT.createKey(
+                                        SigninPreferencesManager.SyncPromoAccessPointId.NTP)));
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signOutSyncingAccountFromJavaWithNullDomainAndForceWipe() {
         when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
                         eq(NATIVE_IDENTITY_MANAGER), anyInt()))
@@ -358,11 +581,33 @@
         verify(mNativeMock, never()).wipeGoogleServiceWorkerCaches(anyLong(), any());
     }
 
+    @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void
+            signOutSyncingAccountFromJavaWithNullDomainAndForceWipe_seedAccountsRevampEnabled() {
+        when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                        eq(NATIVE_IDENTITY_MANAGER), anyInt()))
+                .thenReturn(ACCOUNT_INFO);
+
+        mSigninManager.signOut(SignoutReason.TEST, null, true);
+
+        // The primary account should be cleared *before* clearing any account data.
+        // For more information see crbug.com/589028.
+        InOrder inOrder = inOrder(mNativeMock, mIdentityMutator);
+        inOrder.verify(mIdentityMutator).clearPrimaryAccount(eq(SignoutReason.TEST), anyInt());
+
+        // Sign-out should only clear the profile when the user is syncing and has decided to
+        // wipe data.
+        inOrder.verify(mNativeMock).wipeProfileData(eq(NATIVE_SIGNIN_MANAGER), any());
+        verify(mNativeMock, never()).wipeGoogleServiceWorkerCaches(anyLong(), any());
+    }
+
     // TODO(crbug.com/1294761): add test for revokeSyncConsentFromJavaWithManagedDomain() and
     // revokeSyncConsentFromJavaWipeData() - this requires making the BookmarkModel mockable in
     // SigninManagerImpl.
 
     @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void revokeSyncConsentFromJavaWithNullDomain() {
         SigninManager.SignOutCallback callback = mock(SigninManager.SignOutCallback.class);
         when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
@@ -383,6 +628,28 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void revokeSyncConsentFromJavaWithNullDomain_seedAccountsRevampEnabled() {
+        SigninManager.SignOutCallback callback = mock(SigninManager.SignOutCallback.class);
+        when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                        eq(NATIVE_IDENTITY_MANAGER), anyInt()))
+                .thenReturn(ACCOUNT_INFO);
+
+        mSigninManager.revokeSyncConsent(SignoutReason.TEST, callback, false);
+
+        // The primary account should be cleared *before* clearing any account data.
+        // For more information see crbug.com/589028.
+        InOrder inOrder = inOrder(mNativeMock, mIdentityMutator);
+        inOrder.verify(mIdentityMutator).revokeSyncConsent(eq(SignoutReason.TEST), anyInt());
+
+        // Disabling sync should only clear the service worker cache when the user is neither
+        // managed or syncing.
+        verify(mNativeMock, never()).wipeProfileData(anyLong(), any());
+        inOrder.verify(mNativeMock).wipeGoogleServiceWorkerCaches(anyLong(), any());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void clearingAccountCookieDoesNotTriggerSignoutWhenUserIsSignedOut() {
         mFakeAccountManagerFacade.addAccount(
                 AccountUtils.createAccountFromName(ACCOUNT_INFO.getEmail()));
@@ -395,6 +662,21 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void
+            clearingAccountCookieDoesNotTriggerSignoutWhenUserIsSignedOut_seedAccountsRevampEnabled() {
+        mFakeAccountManagerFacade.addAccount(
+                AccountUtils.createAccountFromName(ACCOUNT_INFO.getEmail()));
+
+        mIdentityManager.onAccountsCookieDeletedByUserAction();
+
+        verify(mIdentityMutator, never()).clearPrimaryAccount(anyInt(), anyInt());
+        verify(mNativeMock, never()).wipeProfileData(anyLong(), any());
+        verify(mNativeMock, never()).wipeGoogleServiceWorkerCaches(anyLong(), any());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void clearingAccountCookieDoesNotTriggerSignoutWhenUserIsSignedInAndSync() {
         when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
                         eq(NATIVE_IDENTITY_MANAGER), anyInt()))
@@ -410,6 +692,24 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void
+            clearingAccountCookieDoesNotTriggerSignoutWhenUserIsSignedInAndSync_seedAccountsRevampEnabled() {
+        when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                        eq(NATIVE_IDENTITY_MANAGER), anyInt()))
+                .thenReturn(ACCOUNT_INFO);
+        mFakeAccountManagerFacade.addAccount(
+                AccountUtils.createAccountFromName(ACCOUNT_INFO.getEmail()));
+
+        mIdentityManager.onAccountsCookieDeletedByUserAction();
+
+        verify(mIdentityMutator, never()).clearPrimaryAccount(anyInt(), anyInt());
+        verify(mNativeMock, never()).wipeProfileData(anyLong(), any());
+        verify(mNativeMock, never()).wipeGoogleServiceWorkerCaches(anyLong(), any());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void clearingAccountCookieDoesNotTriggerSignoutWhenUserIsSignedInWithoutSync() {
         when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
                         NATIVE_IDENTITY_MANAGER, ConsentLevel.SIGNIN))
@@ -425,6 +725,24 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void
+            clearingAccountCookieDoesNotTriggerSignoutWhenUserIsSignedInWithoutSync_seedAccountsRevampEnabled() {
+        when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                        NATIVE_IDENTITY_MANAGER, ConsentLevel.SIGNIN))
+                .thenReturn(ACCOUNT_INFO);
+        mFakeAccountManagerFacade.addAccount(
+                AccountUtils.createAccountFromName(ACCOUNT_INFO.getEmail()));
+
+        mIdentityManager.onAccountsCookieDeletedByUserAction();
+
+        verify(mIdentityMutator, never()).clearPrimaryAccount(anyInt(), anyInt());
+        verify(mNativeMock, never()).wipeProfileData(anyLong(), any());
+        verify(mNativeMock, never()).wipeGoogleServiceWorkerCaches(anyLong(), any());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void callbackNotifiedWhenNoOperationIsInProgress() {
         AtomicInteger callCount = new AtomicInteger(0);
 
@@ -433,10 +751,22 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void callbackNotifiedWhenNoOperationIsInProgress_seedAccountsRevampEnabled() {
+        AtomicInteger callCount = new AtomicInteger(0);
+
+        mSigninManager.runAfterOperationInProgress(callCount::incrementAndGet);
+        assertEquals(1, callCount.get());
+    }
+
+    @Test
     // TODO(crbug.com/1353777): Disabling the feature explicitly, because native is not available to
     // provide a default value. This should be enabled if the feature is enabled by default or
     // removed if the flag is removed.
-    @DisableFeatures(ChromeFeatureList.SYNC_ANDROID_LIMIT_NTP_PROMO_IMPRESSIONS)
+    @DisableFeatures({
+        ChromeFeatureList.SYNC_ANDROID_LIMIT_NTP_PROMO_IMPRESSIONS,
+        ChromeFeatureList.SEED_ACCOUNTS_REVAMP
+    })
     public void callbackNotifiedOnSignout() {
         doAnswer(
                         invocation -> {
@@ -459,6 +789,34 @@
     }
 
     @Test
+    // TODO(crbug.com/1353777): Disabling the feature explicitly, because native is not available to
+    // provide a default value. This should be enabled if the feature is enabled by default or
+    // removed if the flag is removed.
+    @DisableFeatures(ChromeFeatureList.SYNC_ANDROID_LIMIT_NTP_PROMO_IMPRESSIONS)
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void callbackNotifiedOnSignout_seedAccountsRevampEnabled() {
+        doAnswer(
+                        invocation -> {
+                            mIdentityManager.onPrimaryAccountChanged(
+                                    new PrimaryAccountChangeEvent(
+                                            PrimaryAccountChangeEvent.Type.CLEARED,
+                                            PrimaryAccountChangeEvent.Type.NONE));
+                            return null;
+                        })
+                .when(mIdentityMutator)
+                .clearPrimaryAccount(anyInt(), anyInt());
+
+        mSigninManager.signOut(SignoutReason.TEST);
+        AtomicInteger callCount = new AtomicInteger(0);
+        mSigninManager.runAfterOperationInProgress(callCount::incrementAndGet);
+        assertEquals(0, callCount.get());
+
+        mSigninManager.finishSignOut();
+        assertEquals(1, callCount.get());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void callbackNotifiedOnSignin() {
         final Answer<Integer> setPrimaryAccountAnswer =
                 invocation -> {
@@ -486,7 +844,35 @@
         assertEquals(1, callCount.get());
     }
 
+    @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void callbackNotifiedOnSignin_seedAccountsRevampEnabled() {
+        mFakeAccountManagerFacade.addAccount(ACCOUNT_FROM_INFO);
+        final Answer<Integer> setPrimaryAccountAnswer =
+                invocation -> {
+                    // From now on getPrimaryAccountInfo should return account.
+                    when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                                    eq(NATIVE_IDENTITY_MANAGER), anyInt()))
+                            .thenReturn(ACCOUNT_INFO);
+                    return PrimaryAccountError.NO_ERROR;
+                };
+        doAnswer(setPrimaryAccountAnswer)
+                .when(mIdentityMutator)
+                .setPrimaryAccount(
+                        ACCOUNT_INFO.getId(), ConsentLevel.SYNC, SigninAccessPoint.UNKNOWN);
+
+        mSigninManager.signinAndEnableSync(ACCOUNT_FROM_INFO, SigninAccessPoint.UNKNOWN, null);
+
+        AtomicInteger callCount = new AtomicInteger(0);
+        mSigninManager.runAfterOperationInProgress(callCount::incrementAndGet);
+        assertEquals(0, callCount.get());
+
+        mSigninManager.finishSignInAfterPolicyEnforced();
+        assertEquals(1, callCount.get());
+    }
+
     @Test(expected = AssertionError.class)
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signinfailsWhenAlreadySignedIn() {
         when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
                         eq(NATIVE_IDENTITY_MANAGER), anyInt()))
@@ -497,7 +883,20 @@
                 null);
     }
 
+    @Test(expected = AssertionError.class)
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void signinfailsWhenAlreadySignedIn_seedAccountsRevampEnabled() {
+        when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                        eq(NATIVE_IDENTITY_MANAGER), anyInt()))
+                .thenReturn(ACCOUNT_INFO);
+        mSigninManager.signinAndEnableSync(
+                AccountUtils.createAccountFromName(ACCOUNT_INFO.getEmail()),
+                SigninAccessPoint.UNKNOWN,
+                null);
+    }
+
     @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signInStateObserverCallOnSignIn() {
         final Answer<Integer> setPrimaryAccountAnswer =
                 invocation -> {
@@ -527,7 +926,44 @@
     }
 
     @Test
-    @DisableFeatures(ChromeFeatureList.SYNC_ANDROID_LIMIT_NTP_PROMO_IMPRESSIONS)
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void signInStateObserverCallOnSignIn_seedAccountsRevampEnabled() {
+        mFakeAccountManagerFacade.addAccount(ACCOUNT_FROM_INFO);
+        List<CoreAccountInfo> coreAccountInfos =
+                mFakeAccountManagerFacade.getCoreAccountInfos().getResult();
+        CoreAccountInfo primaryAccountInfo =
+                AccountUtils.findCoreAccountInfoByEmail(coreAccountInfos, ACCOUNT_INFO.getEmail());
+        final Answer<Integer> setPrimaryAccountAnswer =
+                invocation -> {
+                    // From now on getPrimaryAccountInfo should return account.
+                    when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                                    eq(NATIVE_IDENTITY_MANAGER), anyInt()))
+                            .thenReturn(primaryAccountInfo);
+                    return PrimaryAccountError.NO_ERROR;
+                };
+        doAnswer(setPrimaryAccountAnswer)
+                .when(mIdentityMutator)
+                .setPrimaryAccount(
+                        primaryAccountInfo.getId(),
+                        ConsentLevel.SYNC,
+                        SigninAccessPoint.START_PAGE);
+
+        mSigninManager.signinAndEnableSync(ACCOUNT_FROM_INFO, SigninAccessPoint.START_PAGE, null);
+        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+        verify(mSignInStateObserver).onSignInAllowedChanged();
+
+        mSigninManager.finishSignInAfterPolicyEnforced();
+        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+        verify(mSignInStateObserver).onSignOutAllowedChanged();
+        assertFalse(mSigninManager.isSigninAllowed());
+        assertTrue(mSigninManager.isSignOutAllowed());
+    }
+
+    @Test
+    @DisableFeatures({
+        ChromeFeatureList.SYNC_ANDROID_LIMIT_NTP_PROMO_IMPRESSIONS,
+        ChromeFeatureList.SEED_ACCOUNTS_REVAMP
+    })
     public void signInStateObserverCallOnSignOut() {
         when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
                         eq(NATIVE_IDENTITY_MANAGER), anyInt()))
@@ -541,6 +977,22 @@
     }
 
     @Test
+    @DisableFeatures(ChromeFeatureList.SYNC_ANDROID_LIMIT_NTP_PROMO_IMPRESSIONS)
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void signInStateObserverCallOnSignOut_seedAccountsRevampEnabled() {
+        when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                        eq(NATIVE_IDENTITY_MANAGER), anyInt()))
+                .thenReturn(ACCOUNT_INFO);
+        assertTrue(mSigninManager.isSignOutAllowed());
+
+        mSigninManager.signOut(SignoutReason.TEST);
+        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+        verify(mSignInStateObserver).onSignOutAllowedChanged();
+        assertFalse(mSigninManager.isSignOutAllowed());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signOutNotAllowedForChildAccounts() {
         when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
                         eq(NATIVE_IDENTITY_MANAGER), anyInt()))
@@ -552,6 +1004,19 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void signOutNotAllowedForChildAccounts_seedAccountsRevampEnabled() {
+        when(mIdentityManagerNativeMock.getPrimaryAccountInfo(
+                        eq(NATIVE_IDENTITY_MANAGER), anyInt()))
+                .thenReturn(ACCOUNT_INFO);
+        when(mIdentityManagerNativeMock.isClearPrimaryAccountAllowed(NATIVE_IDENTITY_MANAGER))
+                .thenReturn(false);
+
+        assertFalse(mSigninManager.isSignOutAllowed());
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signInShouldBeSupportedForNonDemoUsers() {
         when(mExternalAuthUtils.canUseGooglePlayServices()).thenReturn(true);
 
@@ -566,6 +1031,22 @@
     }
 
     @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void signInShouldBeSupportedForNonDemoUsers_seedAccountsRevampEnabled() {
+        when(mExternalAuthUtils.canUseGooglePlayServices()).thenReturn(true);
+
+        // Make sure that the user is not a demo user.
+        ShadowApplication shadowApplication = ShadowApplication.getInstance();
+        UserManager userManager = Mockito.mock(UserManager.class);
+        Mockito.when(userManager.isDemoUser()).thenReturn(false);
+        shadowApplication.setSystemService(Context.USER_SERVICE, userManager);
+
+        assertTrue(mSigninManager.isSigninSupported(/* requireUpdatedPlayServices= */ true));
+        assertTrue(mSigninManager.isSigninSupported(/* requireUpdatedPlayServices= */ false));
+    }
+
+    @Test
+    @DisableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
     public void signInShouldNotBeSupportedWhenGooglePlayServicesIsRequiredAndNotAvailable() {
         when(mExternalAuthUtils.canUseGooglePlayServices()).thenReturn(false);
 
@@ -577,4 +1058,19 @@
 
         assertFalse(mSigninManager.isSigninSupported(/* requireUpdatedPlayServices= */ true));
     }
+
+    @Test
+    @EnableFeatures(ChromeFeatureList.SEED_ACCOUNTS_REVAMP)
+    public void
+            signInShouldNotBeSupportedWhenGooglePlayServicesIsRequiredAndNotAvailable_seedAccountsRevampEnabled() {
+        when(mExternalAuthUtils.canUseGooglePlayServices()).thenReturn(false);
+
+        // Make sure that the user is not a demo user.
+        ShadowApplication shadowApplication = ShadowApplication.getInstance();
+        UserManager userManager = Mockito.mock(UserManager.class);
+        Mockito.when(userManager.isDemoUser()).thenReturn(false);
+        shadowApplication.setSystemService(Context.USER_SERVICE, userManager);
+
+        assertFalse(mSigninManager.isSigninSupported(/* requireUpdatedPlayServices= */ true));
+    }
 }
diff --git a/chrome/android/profiles/arm.newest.txt b/chrome/android/profiles/arm.newest.txt
index 06760b5..8043d7a 100644
--- a/chrome/android/profiles/arm.newest.txt
+++ b/chrome/android/profiles/arm.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-121.0.6109.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-arm-121.0.6110.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index b0d8ad5..74ba3eb 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-121.0.6109.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-121.0.6110.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 77359bb..705046ac 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -2196,9 +2196,13 @@
         Scanning for malware...
       </message>
       <message name="IDS_BLOCK_REASON_PROMPT_FOR_SCANNING_UPDATED"
-               desc="Message shown to the user on chrome://downloads page to explain that this download is recommended to be scanned.">
+          desc="Message shown to the user on chrome://downloads page to explain that this download is recommended to be scanned.">
         This file might be a virus or malware. You can send it to Google to check if it's unsafe.
       </message>
+      <message name="IDS_BLOCK_REASON_PROMPT_FOR_LOCAL_PASSWORD_SCANNING"
+          desc="Message shown to the user on chrome://downloads page to explain that this download is recommended to be scanned.">
+        This file may be dangerous
+      </message>
       <message name="IDS_DEEP_SCANNED_OPENED_DANGEROUS_DESCRIPTION"
         desc="Message shown to the user on chrome://downloads page to explain this this download was deep scanned, and found to be malicious.">
         This file is dangerous
@@ -7834,24 +7838,33 @@
       <message name="IDS_NTP_WEBSTORE_TOAST_BUTTON_TEXT" desc="The text displayed in the New Tab Page webstore themes toast button">
         Find themes
       </message>
-      <message name="IDS_NTP_WALLPAPER_SEARCH_GENERIC_ERROR_TITLE" desc="The title of the generic error displayed when wallpaper search fails.">
-        Something went wrong.
-      </message>
       <message name="IDS_NTP_WALLPAPER_SEARCH_GENERIC_ERROR_DESCRIPTION" desc="The description of the generic error displayed when wallpaper search fails.">
         Please try again later.
       </message>
+      <message name="IDS_NTP_WALLPAPER_SEARCH_GENERIC_ERROR_TITLE" desc="The title of the generic error displayed when wallpaper search fails.">
+        Something went wrong.
+      </message>
       <message name="IDS_NTP_WALLPAPER_SEARCH_HEADER" translateable="false" desc="Header for the wallpaper search page of Customize Chrome Side Panel." >
         Wallpaper Search
       </message>
       <message name="IDS_NTP_WALLPAPER_SEARCH_HISTORY_HEADER" translateable="false" desc="Header for the wallpaper search section for showing past themes." >
         Your recent themes
       </message>
+      <message name="IDS_NTP_WALLPAPER_SEARCH_REQUEST_THROTTLED_DESCRIPTION" desc="The description of the message displayed when a wallpaper search request is throttled.">
+        You can try again tomorrow.
+      </message>
+      <message name="IDS_NTP_WALLPAPER_SEARCH_REQUEST_THROTTLED_TITLE" desc="The title of the message displayed when a wallpaper search request is throttled.">
+        You've reached your limit for today.
+      </message>
       <message name="IDS_NTP_WALLPAPER_SEARCH_SUBMIT_AGAIN_BTN_TEXT" translateable="false" desc="Button text for submitting the form to get wallpaper search results when the user has already done it before." >
         Search Again
       </message>
       <message name="IDS_NTP_WALLPAPER_SEARCH_SUBMIT_BTN_TEXT" translateable="false" desc="Button text for submitting the form to get wallpaper search results." >
         Search
       </message>
+      <message name="IDS_NTP_WALLPAPER_SEARCH_TRY_AGAIN_CTA" desc="Call to action displayed when wallpaper search fails that asks user to try again.">
+        Try again
+      </message>
 
       <!-- NTP Modules -->
       <message name="IDS_NTP_MODULES_INFO_BUTTON_TITLE" desc="Text shown in tooltip of info button of an NTP module.">
@@ -16395,6 +16408,12 @@
         =1 {Checking public key and integrity block... 1 minute remaining}
         other {Checking public key and integrity block... # minutes remaining}}
     </message>
+    <message name="IDS_IWA_INSTALLER_VERIFICATION_ERROR_TITLE" desc="Title of an error popup during the verification step of the Isolated Web App installer">
+      Chrome failed to verify this installation bundle
+    </message>
+    <message name="IDS_IWA_INSTALLER_VERIFICATION_ERROR_SUBTITLE" desc="Subtitle of an error popup during the verification step of the Isolated Web App installer">
+      This bundle might be broken or compromised. Please close this window and download it again
+    </message>
   </messages>
 </release>
 </grit>
diff --git a/chrome/app/generated_resources_grd/IDS_BLOCK_REASON_PROMPT_FOR_LOCAL_PASSWORD_SCANNING.png.sha1 b/chrome/app/generated_resources_grd/IDS_BLOCK_REASON_PROMPT_FOR_LOCAL_PASSWORD_SCANNING.png.sha1
new file mode 100644
index 0000000..232a658
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_BLOCK_REASON_PROMPT_FOR_LOCAL_PASSWORD_SCANNING.png.sha1
@@ -0,0 +1 @@
+a704596a79f6b712a38ba009dce5527eba92b5ea
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_IWA_INSTALLER_VERIFICATION_ERROR_SUBTITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_IWA_INSTALLER_VERIFICATION_ERROR_SUBTITLE.png.sha1
new file mode 100644
index 0000000..b46d2d8d
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_IWA_INSTALLER_VERIFICATION_ERROR_SUBTITLE.png.sha1
@@ -0,0 +1 @@
+2838e48c94bf481a50d609b3ea1384ed31d9f7ae
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_IWA_INSTALLER_VERIFICATION_ERROR_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_IWA_INSTALLER_VERIFICATION_ERROR_TITLE.png.sha1
new file mode 100644
index 0000000..13b0b81
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_IWA_INSTALLER_VERIFICATION_ERROR_TITLE.png.sha1
@@ -0,0 +1 @@
+bd865579c40a5f0c75b1005502a5e3b05756ce79
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_WALLPAPER_SEARCH_REQUEST_THROTTLED_DESCRIPTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_WALLPAPER_SEARCH_REQUEST_THROTTLED_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..8477c9e
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_WALLPAPER_SEARCH_REQUEST_THROTTLED_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+00e0d191d86d1ce428e1a2c93ba3fc7fcf3710c3
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_WALLPAPER_SEARCH_REQUEST_THROTTLED_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_WALLPAPER_SEARCH_REQUEST_THROTTLED_TITLE.png.sha1
new file mode 100644
index 0000000..8477c9e
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_WALLPAPER_SEARCH_REQUEST_THROTTLED_TITLE.png.sha1
@@ -0,0 +1 @@
+00e0d191d86d1ce428e1a2c93ba3fc7fcf3710c3
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_WALLPAPER_SEARCH_TRY_AGAIN_CTA.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_WALLPAPER_SEARCH_TRY_AGAIN_CTA.png.sha1
new file mode 100644
index 0000000..0d9a9cf
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_WALLPAPER_SEARCH_TRY_AGAIN_CTA.png.sha1
@@ -0,0 +1 @@
+c39e44e27e17afde5df0e42885b81865f4ebdf4a
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings.grdp b/chrome/app/os_settings_search_tag_strings.grdp
index 0d34e08..9688fdb 100644
--- a/chrome/app/os_settings_search_tag_strings.grdp
+++ b/chrome/app/os_settings_search_tag_strings.grdp
@@ -80,6 +80,12 @@
   <message name="IDS_OS_SETTINGS_TAG_CELLULAR_APN" desc="Text for search result item which, when clicked, navigates the user to Cellular network settings, with the option to set up APNs. Alternate phrase for: 'Wi-Fi networks', 'Wireless'">
     Cellular APN
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_CELLULAR_APN_SETTINGS" desc="Text for search result item which, when clicked, navigates the user to the 'Access Point name (APN)' settings subpage of the currently active cellular network. Alternate phrase for 'Access point name (APN)'">
+    Cellular APN settings
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_CELLULAR_APN_SETTINGS_ALT_1" desc="Text for search result item which, when clicked, navigates the user to the 'Access Point name (APN)' settings subpage of the currently active cellular network. Alternate phrase for 'Cellular APN settings'">
+    Access point name (APN)
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_CELLULAR_TURN_OFF" desc="Text for search result item which, when clicked, navigates the user to cellular network settings, with a toggle to turn off cellular. Alternate phrase for: 'Disable cellular'">
     Turn off Cellular network
   </message>
@@ -95,6 +101,12 @@
   <message name="IDS_OS_SETTINGS_TAG_ADD_ESIM_ALT2" desc="Text for search result item which, when clicked, navigates the user to cellular network settings, with an add eSIM icon button. Alternate phrase for: 'Add eSIM profile', 'Install eSIM profile'">
     Download eSIM profile
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_ADD_APN" desc="Text for search result item which, when clicked, navigates the user to the APN (Accesss Point Name) subpage of the currently active cellular network, with the add New APN button focused. Alternate phrase for: 'Add new Access Point Name'">
+    Add new APN
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_ADD_APN_ALT1" desc="Text for search result item which, when clicked, navigates the user to the APN (Accesss Point Name) subpage of the currently active cellular network, with the add New APN button focused. Alternate phrase for: 'Add new APN'">
+    Add new Access point name
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_CELLULAR_TURN_ON" desc="Text for search result item which, when clicked, navigates the user to cellular network settings, with a toggle to turn on cellular. Alternate phrase for: 'Enable cellular'">
     Turn on Cellular network
   </message>
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_ADD_APN.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_ADD_APN.png.sha1
new file mode 100644
index 0000000..755b3a1f
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_ADD_APN.png.sha1
@@ -0,0 +1 @@
+590ad970ad9779505891f31272360b8137f98fce
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_ADD_APN_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_ADD_APN_ALT1.png.sha1
new file mode 100644
index 0000000..d6128b3
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_ADD_APN_ALT1.png.sha1
@@ -0,0 +1 @@
+c1fc04775a09cd10a2ffd60894e71cdde00e3259
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_CELLULAR_APN_SETTINGS.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_CELLULAR_APN_SETTINGS.png.sha1
new file mode 100644
index 0000000..755b3a1f
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_CELLULAR_APN_SETTINGS.png.sha1
@@ -0,0 +1 @@
+590ad970ad9779505891f31272360b8137f98fce
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_CELLULAR_APN_SETTINGS_ALT_1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_CELLULAR_APN_SETTINGS_ALT_1.png.sha1
new file mode 100644
index 0000000..e3195fb
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_CELLULAR_APN_SETTINGS_ALT_1.png.sha1
@@ -0,0 +1 @@
+9d746803901021da45215ce7c0ac5c34770d9b25
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index baecebb..ca1b110 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -1209,6 +1209,9 @@
   </message>
 
   <!-- A11y (OS Settings) -->
+  <message name="IDS_OS_SETTINGS_ACCESSIBILITY_MENU_ITEM_DESCRIPTION" desc="Description for the Accessibility menu item in the left menu.">
+    Screen reader, magnification
+  </message>
   <message name="IDS_SETTINGS_OPTIONS_IN_MENU_LABEL" desc="Label for checkbox which enables showing accessibility options in the system menu.">
     Show accessibility options in Quick Settings
   </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ACCESSIBILITY_MENU_ITEM_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ACCESSIBILITY_MENU_ITEM_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..5f1e033a
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ACCESSIBILITY_MENU_ITEM_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+01d8d7f3a6bb523883fb1f1107cf78d0d706a8b0
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 0e5447a..8be0ce7 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3653,6 +3653,48 @@
              kTpcdWritePopupCurrentInteractionHeuristicsGrantsName,
          "30d"},
         {tpcd::experiment::kTpcdBackfillPopupHeuristicsGrantsName, "30d"}};
+const FeatureEntry::FeatureParam
+    kTpcdHeuristicsGrantsCurrentInteractionAndShortRedirect[] = {
+        {content_settings::features::kTpcdReadHeuristicsGrantsName, "true"},
+        {tpcd::experiment::
+             kTpcdWritePopupCurrentInteractionHeuristicsGrantsName,
+         "30d"},
+        {tpcd::experiment::kTpcdWriteRedirectHeuristicGrantsName, "15m"},
+        {tpcd::experiment::kTpcdRedirectHeuristicRequireABAFlowName, "true"},
+        {tpcd::experiment::kTpcdRedirectHeuristicRequireCurrentInteractionName,
+         "true"}};
+const FeatureEntry::FeatureParam
+    kTpcdHeuristicsGrantsCurrentInteractionAndLongRedirect[] = {
+        {content_settings::features::kTpcdReadHeuristicsGrantsName, "true"},
+        {tpcd::experiment::
+             kTpcdWritePopupCurrentInteractionHeuristicsGrantsName,
+         "30d"},
+        {tpcd::experiment::kTpcdWriteRedirectHeuristicGrantsName, "30d"},
+        {tpcd::experiment::kTpcdRedirectHeuristicRequireABAFlowName, "true"},
+        {tpcd::experiment::kTpcdRedirectHeuristicRequireCurrentInteractionName,
+         "true"}};
+const FeatureEntry::FeatureParam
+    kTpcdHeuristicsGrantsCurrentInteractionWithBackfillAndShortRedirect[] = {
+        {content_settings::features::kTpcdReadHeuristicsGrantsName, "true"},
+        {tpcd::experiment::
+             kTpcdWritePopupCurrentInteractionHeuristicsGrantsName,
+         "30d"},
+        {tpcd::experiment::kTpcdBackfillPopupHeuristicsGrantsName, "30d"},
+        {tpcd::experiment::kTpcdWriteRedirectHeuristicGrantsName, "15m"},
+        {tpcd::experiment::kTpcdRedirectHeuristicRequireABAFlowName, "true"},
+        {tpcd::experiment::kTpcdRedirectHeuristicRequireCurrentInteractionName,
+         "true"}};
+const FeatureEntry::FeatureParam
+    kTpcdHeuristicsGrantsCurrentInteractionWithBackfillAndLongRedirect[] = {
+        {content_settings::features::kTpcdReadHeuristicsGrantsName, "true"},
+        {tpcd::experiment::
+             kTpcdWritePopupCurrentInteractionHeuristicsGrantsName,
+         "30d"},
+        {tpcd::experiment::kTpcdBackfillPopupHeuristicsGrantsName, "30d"},
+        {tpcd::experiment::kTpcdWriteRedirectHeuristicGrantsName, "30d"},
+        {tpcd::experiment::kTpcdRedirectHeuristicRequireABAFlowName, "true"},
+        {tpcd::experiment::kTpcdRedirectHeuristicRequireCurrentInteractionName,
+         "true"}};
 
 const FeatureEntry::FeatureVariation kTpcdHeuristicsGrantsVariations[] = {
     {"Control", kTpcdHeuristicsGrantsControl,
@@ -3661,7 +3703,25 @@
      std::size(kTpcdHeuristicsGrantsCurrentInteraction), nullptr},
     {"Current Interaction With Backfill",
      kTpcdHeuristicsGrantsCurrentInteractionWithBackfill,
-     std::size(kTpcdHeuristicsGrantsCurrentInteractionWithBackfill), nullptr}};
+     std::size(kTpcdHeuristicsGrantsCurrentInteractionWithBackfill), nullptr},
+    {"Current Interaction And Short Redirect",
+     kTpcdHeuristicsGrantsCurrentInteractionAndShortRedirect,
+     std::size(kTpcdHeuristicsGrantsCurrentInteractionAndShortRedirect),
+     nullptr},
+    {"Current Interaction And Long Redirect",
+     kTpcdHeuristicsGrantsCurrentInteractionAndLongRedirect,
+     std::size(kTpcdHeuristicsGrantsCurrentInteractionAndLongRedirect),
+     nullptr},
+    {"Current Interaction With Backfill And Short Redirect",
+     kTpcdHeuristicsGrantsCurrentInteractionWithBackfillAndShortRedirect,
+     std::size(
+         kTpcdHeuristicsGrantsCurrentInteractionWithBackfillAndShortRedirect),
+     nullptr},
+    {"Current Interaction With Backfill And Long Redirect",
+     kTpcdHeuristicsGrantsCurrentInteractionWithBackfillAndLongRedirect,
+     std::size(
+         kTpcdHeuristicsGrantsCurrentInteractionWithBackfillAndLongRedirect),
+     nullptr}};
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 const FeatureEntry::FeatureParam kVcSegmentationModelHighResolution[] = {
@@ -7150,11 +7210,6 @@
 #endif  // BUILDFLAG(ENABLE_PRINTING)
 
 #if BUILDFLAG(IS_WIN)
-    {"enable-windows-gaming-input-data-fetcher",
-     flag_descriptions::kEnableWindowsGamingInputDataFetcherName,
-     flag_descriptions::kEnableWindowsGamingInputDataFetcherDescription, kOsWin,
-     FEATURE_VALUE_TYPE(features::kEnableWindowsGamingInputDataFetcher)},
-
     {"windows11-mica-titlebar", flag_descriptions::kWindows11MicaTitlebarName,
      flag_descriptions::kWindows11MicaTitlebarDescription, kOsWin,
      FEATURE_VALUE_TYPE(kWindows11MicaTitlebar)},
@@ -9099,10 +9154,6 @@
      flag_descriptions::kFedCmIdpSigninStatusDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kFedCmIdpSigninStatusEnabled)},
 
-    {"fedcm-logout-rps", flag_descriptions::kFedCmLogoutRpsName,
-     flag_descriptions::kFedCmLogoutRpsDescription, kOsAll,
-     FEATURE_VALUE_TYPE(features::kFedCmLogoutRps)},
-
     {"fedcm-metrics-endpoint", flag_descriptions::kFedCmMetricsEndpointName,
      flag_descriptions::kFedCmMetricsEndpointDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kFedCmMetricsEndpoint)},
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index 261308ea..203be8a 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -1494,6 +1494,8 @@
     "input_method/editor_event_sink.h",
     "input_method/editor_feedback.cc",
     "input_method/editor_feedback.h",
+    "input_method/editor_helpers.cc",
+    "input_method/editor_helpers.h",
     "input_method/editor_mediator.cc",
     "input_method/editor_mediator.h",
     "input_method/editor_mediator_factory.cc",
@@ -5484,6 +5486,7 @@
     "input_method/diacritics_insensitive_string_comparator_unittest.cc",
     "input_method/editor_consent_store_unittest.cc",
     "input_method/editor_feedback_unittest.cc",
+    "input_method/editor_helpers_unittest.cc",
     "input_method/editor_switch_unittest.cc",
     "input_method/emoji_suggester_unittest.cc",
     "input_method/fake_suggestion_handler.cc",
diff --git a/chrome/browser/ash/accessibility/speech_monitor.cc b/chrome/browser/ash/accessibility/speech_monitor.cc
index 3692811c..d550659 100644
--- a/chrome/browser/ash/accessibility/speech_monitor.cc
+++ b/chrome/browser/ash/accessibility/speech_monitor.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ash/accessibility/speech_monitor.h"
 
+#include "base/containers/contains.h"
 #include "base/strings/pattern.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -143,8 +144,7 @@
     const content::VoiceData& voice_data) {
   if (!utterance_queue_.empty() &&
       utterance_queue_.back().text == utterance->GetText() &&
-      std::find(repeated_speech_.begin(), repeated_speech_.end(),
-                utterance->GetText()) == repeated_speech_.end()) {
+      !base::Contains(repeated_speech_, utterance->GetText())) {
     repeated_speech_.push_back(utterance->GetText());
   }
 
diff --git a/chrome/browser/ash/app_mode/kiosk_app.cc b/chrome/browser/ash/app_mode/kiosk_app.cc
index cba89c080..65a5929 100644
--- a/chrome/browser/ash/app_mode/kiosk_app.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app.cc
@@ -5,16 +5,23 @@
 #include "chrome/browser/ash/app_mode/kiosk_app.h"
 
 #include <string>
+#include <string_view>
 
 #include "chrome/browser/ash/app_mode/kiosk_app_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/image/image_skia.h"
+#include "url/gurl.h"
 
 namespace ash {
 
 KioskApp::KioskApp(const KioskAppId& id,
-                   const std::string& name,
-                   gfx::ImageSkia icon)
-    : id_(id), name_(name), icon_(icon) {}
+                   std::string_view name,
+                   gfx::ImageSkia icon,
+                   absl::optional<GURL> url)
+    : id_(id), name_(name), icon_(icon), url_(std::move(url)) {
+  bool should_have_url = id_.type == KioskAppType::kWebApp;
+  CHECK_EQ(should_have_url, url.has_value());
+}
 
 KioskApp::KioskApp(const KioskApp&) = default;
 KioskApp::KioskApp(KioskApp&&) = default;
diff --git a/chrome/browser/ash/app_mode/kiosk_app.h b/chrome/browser/ash/app_mode/kiosk_app.h
index 74526cf..940ca61 100644
--- a/chrome/browser/ash/app_mode/kiosk_app.h
+++ b/chrome/browser/ash/app_mode/kiosk_app.h
@@ -6,16 +6,22 @@
 #define CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_H_
 
 #include <string>
+#include <string_view>
 
 #include "chrome/browser/ash/app_mode/kiosk_app_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/image/image_skia.h"
+#include "url/gurl.h"
 
 namespace ash {
 
 // Metadata relevant to identify and display a Kiosk app.
 class KioskApp {
  public:
-  KioskApp(const KioskAppId& id, const std::string& name, gfx::ImageSkia icon);
+  KioskApp(const KioskAppId& id,
+           std::string_view name,
+           gfx::ImageSkia icon,
+           absl::optional<GURL> url = absl::nullopt);
   KioskApp(const KioskApp&);
   KioskApp(KioskApp&&);
   ~KioskApp();
@@ -26,14 +32,17 @@
   // The Kiosk id used to identify the app, and determine its type.
   KioskAppId id() const { return id_; }
   // The application name as displayed in the UI.
-  std::string name() const { return name_; }
+  std::string_view name() const { return name_; }
   // The application icon as displayed in the UI.
   gfx::ImageSkia icon() const { return icon_; }
+  // The application URL as displayed in the UI. Only present in web apps.
+  const absl::optional<GURL>& url() const { return url_; }
 
  private:
   KioskAppId id_;
   std::string name_;
   gfx::ImageSkia icon_;
+  absl::optional<GURL> url_;
 };
 
 }  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_app_types.cc b/chrome/browser/ash/app_mode/kiosk_app_types.cc
index bc244f9d..82700bb 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_types.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_types.cc
@@ -4,17 +4,26 @@
 
 #include "chrome/browser/ash/app_mode/kiosk_app_types.h"
 
+#include <algorithm>
 #include <ostream>
 #include <string>
+#include <string_view>
 
 #include "base/check.h"
 #include "components/account_id/account_id.h"
+#include "components/crx_file/id_util.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
 
 namespace {
 
+void CheckChromeAppIdIsValid(std::string_view id) {
+  // TODO(b/304937903) upgrade to CHECK.
+  DUMP_WILL_BE_CHECK(crx_file::id_util::IdIsValid(id))
+      << "Invalid Chrome App ID: " << id;
+}
+
 std::string KioskAppTypeToString(KioskAppType type) {
   switch (type) {
     case KioskAppType::kArcApp:
@@ -29,7 +38,7 @@
 }  // namespace
 
 // static
-KioskAppId KioskAppId::ForChromeApp(const std::string& chrome_app_id,
+KioskAppId KioskAppId::ForChromeApp(std::string_view chrome_app_id,
                                     absl::optional<AccountId> account_id) {
   // TODO(b/304937903) upgrade to CHECK.
   DUMP_WILL_BE_CHECK(!account_id.has_value() || account_id->is_valid());
@@ -51,11 +60,13 @@
 }
 
 KioskAppId::KioskAppId() = default;
-KioskAppId::KioskAppId(const std::string& chrome_app_id,
+KioskAppId::KioskAppId(std::string_view chrome_app_id,
                        absl::optional<AccountId> account_id)
     : type(KioskAppType::kChromeApp),
       app_id(chrome_app_id),
-      account_id(account_id) {}
+      account_id(account_id) {
+  CheckChromeAppIdIsValid(chrome_app_id);
+}
 KioskAppId::KioskAppId(KioskAppType type, const AccountId& account_id)
     : type(type), account_id(account_id) {}
 KioskAppId::KioskAppId(const KioskAppId&) = default;
diff --git a/chrome/browser/ash/app_mode/kiosk_app_types.h b/chrome/browser/ash/app_mode/kiosk_app_types.h
index 2654be47..a061b29 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_types.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_types.h
@@ -6,20 +6,21 @@
 #define CHROME_BROWSER_ASH_APP_MODE_KIOSK_APP_TYPES_H_
 
 #include <string>
+#include <string_view>
 
 #include "components/account_id/account_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
 
-// Type of different kiosk apps to be launched.
+// Supported types of Kiosk apps.
 enum class KioskAppType { kArcApp, kChromeApp, kWebApp };
 
-// Universal identifier for all kiosk apps.
+// Universal identifier for Kiosk apps.
 class KioskAppId {
  public:
   static KioskAppId ForChromeApp(
-      const std::string& chrome_app_id,
+      std::string_view chrome_app_id,
       absl::optional<AccountId> account_id = absl::nullopt);
   static KioskAppId ForWebApp(const AccountId& account_id);
   static KioskAppId ForArcApp(const AccountId& account_id);
@@ -33,12 +34,11 @@
   absl::optional<AccountId> account_id;
 
  private:
-  KioskAppId(const std::string& chrome_app_id,
+  KioskAppId(std::string_view chrome_app_id,
              absl::optional<AccountId> account_id);
   KioskAppId(KioskAppType type, const AccountId& account_id);
 };
 
-// Overload << operator to allow logging of KioskAppId.
 std::ostream& operator<<(std::ostream& stream, const KioskAppId& app_id);
 
 }  // namespace ash
diff --git a/chrome/browser/ash/app_mode/kiosk_controller.cc b/chrome/browser/ash/app_mode/kiosk_controller.cc
index 5f49577c..c047eb6 100644
--- a/chrome/browser/ash/app_mode/kiosk_controller.cc
+++ b/chrome/browser/ash/app_mode/kiosk_controller.cc
@@ -5,13 +5,17 @@
 #include "chrome/browser/ash/app_mode/kiosk_controller.h"
 
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/check.h"
 #include "base/check_deref.h"
+#include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/kiosk_app.h"
+#include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager_base.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_types.h"
+#include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
@@ -24,14 +28,14 @@
   if (!data) {
     return absl::nullopt;
   }
-  return KioskApp(KioskAppId::ForWebApp(account_id), data->name(),
-                  data->icon());
+  return KioskApp(KioskAppId::ForWebApp(account_id), data->name(), data->icon(),
+                  data->install_url());
 }
 
 absl::optional<KioskApp> ChromeAppById(KioskAppManager& manager,
-                                       const std::string& chrome_app_id) {
+                                       std::string_view chrome_app_id) {
   KioskAppManager::App manager_app;
-  if (!manager.GetApp(chrome_app_id, &manager_app)) {
+  if (!manager.GetApp(std::string(chrome_app_id), &manager_app)) {
     return absl::nullopt;
   }
   return KioskApp(
@@ -75,7 +79,7 @@
   std::vector<KioskApp> apps;
   for (const KioskAppManagerBase::App& web_app : web_app_manager_->GetApps()) {
     apps.emplace_back(KioskAppId::ForWebApp(web_app.account_id), web_app.name,
-                      web_app.icon);
+                      web_app.icon, web_app.url);
   }
   for (const KioskAppManagerBase::App& chrome_app :
        chrome_app_manager_->GetApps()) {
@@ -90,6 +94,20 @@
   return apps;
 }
 
+absl::optional<KioskApp> KioskController::GetAppById(
+    const KioskAppId& app_id) const {
+  switch (app_id.type) {
+    case KioskAppType::kWebApp:
+      CHECK(app_id.account_id.has_value());
+      return WebAppById(web_app_manager_.get(), app_id.account_id.value());
+    case KioskAppType::kChromeApp:
+      return ChromeAppById(chrome_app_manager_.get(), app_id.app_id.value());
+    case KioskAppType::kArcApp:
+      CHECK(app_id.account_id.has_value());
+      return ArcAppById(arc_app_manager_.get(), app_id.account_id.value());
+  }
+}
+
 absl::optional<KioskApp> KioskController::GetAutoLaunchApp() const {
   if (const auto& web_account_id = web_app_manager_->GetAutoLaunchAccountId();
       web_account_id.is_valid()) {
diff --git a/chrome/browser/ash/app_mode/kiosk_controller.h b/chrome/browser/ash/app_mode/kiosk_controller.h
index 46cc412..761330d 100644
--- a/chrome/browser/ash/app_mode/kiosk_controller.h
+++ b/chrome/browser/ash/app_mode/kiosk_controller.h
@@ -30,6 +30,7 @@
   ~KioskController();
 
   std::vector<KioskApp> GetApps() const;
+  absl::optional<KioskApp> GetAppById(const KioskAppId& app_id) const;
   absl::optional<KioskApp> GetAutoLaunchApp() const;
 
  private:
diff --git a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.cc b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.cc
index 4372ce6..fe571d9 100644
--- a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.cc
+++ b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.cc
@@ -234,7 +234,6 @@
                const ash::TextInputMethod::InputContext& context) override {
     owner_->Focus(context_id);
   }
-  void OnTouch(ui::EventPointerType pointerType) override {}
   void OnBlur(const std::string& engine_id, int context_id) override {
     owner_->Blur();
   }
diff --git a/chrome/browser/ash/arc/input_method_manager/input_connection_impl_unittest.cc b/chrome/browser/ash/arc/input_method_manager/input_connection_impl_unittest.cc
index 40c196a..4976910 100644
--- a/chrome/browser/ash/arc/input_method_manager/input_connection_impl_unittest.cc
+++ b/chrome/browser/ash/arc/input_method_manager/input_connection_impl_unittest.cc
@@ -38,7 +38,6 @@
   void OnFocus(const std::string& engine_id,
                int context_id,
                const ash::TextInputMethod::InputContext& context) override {}
-  void OnTouch(ui::EventPointerType pointerType) override {}
   void OnBlur(const std::string& engine_id, int context_id) override {}
   void OnKeyEvent(
       const std::string& engine_id,
diff --git a/chrome/browser/ash/borealis/BUILD.gn b/chrome/browser/ash/borealis/BUILD.gn
index 498f8fe1..2b7ce5f5 100644
--- a/chrome/browser/ash/borealis/BUILD.gn
+++ b/chrome/browser/ash/borealis/BUILD.gn
@@ -10,5 +10,4 @@
 mojom("borealis_installer_types_mojom") {
   webui_module_path = "/"
   sources = [ "borealis_types.mojom" ]
-  use_typescript_sources = true
 }
diff --git a/chrome/browser/ash/crosapi/browser_action.cc b/chrome/browser/ash/crosapi/browser_action.cc
index 7900a4a8..9741cad 100644
--- a/chrome/browser/ash/crosapi/browser_action.cc
+++ b/chrome/browser/ash/crosapi/browser_action.cc
@@ -373,6 +373,16 @@
   const int32_t restore_window_id_;
 };
 
+class OpenProfileManagerAction final : public BrowserAction {
+ public:
+  OpenProfileManagerAction() : BrowserAction(true) {}
+
+  void Perform(const VersionedBrowserService& service,
+               BrowserManagerCallback on_performed) override {
+    service.service->OpenProfileManager();
+  }
+};
+
 // static
 std::unique_ptr<BrowserAction> BrowserAction::NewWindow(
     bool incognito,
@@ -460,6 +470,11 @@
       first_non_pinned_tab_index, app_name, restore_window_id);
 }
 
+// static
+std::unique_ptr<BrowserAction> BrowserAction::OpenProfileManager() {
+  return std::make_unique<OpenProfileManagerAction>();
+}
+
 // No window will be opened in the following circumstances:
 // 1. Lacros-chrome is initialized in the Kiosk session
 // 2. Full restore is responsible for restoring/launching Lacros.
diff --git a/chrome/browser/ash/crosapi/browser_action.h b/chrome/browser/ash/crosapi/browser_action.h
index 5bae42c..5d672139 100644
--- a/chrome/browser/ash/crosapi/browser_action.h
+++ b/chrome/browser/ash/crosapi/browser_action.h
@@ -68,6 +68,7 @@
       int32_t first_non_pinned_tab_index,
       base::StringPiece app_name,
       int32_t restore_window_id);
+  static std::unique_ptr<BrowserAction> OpenProfileManager();
 
   // Returns the initial action for the automatic start of Lacros.
   // No window will be opened in the following circumstances:
diff --git a/chrome/browser/ash/crosapi/browser_data_back_migrator_browsertest.cc b/chrome/browser/ash/crosapi/browser_data_back_migrator_browsertest.cc
index e0b2474..e50f897 100644
--- a/chrome/browser/ash/crosapi/browser_data_back_migrator_browsertest.cc
+++ b/chrome/browser/ash/crosapi/browser_data_back_migrator_browsertest.cc
@@ -9,6 +9,7 @@
 #include "base/test/bind.h"
 #include "base/test/test_future.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
+#include "chrome/browser/ash/app_mode/kiosk_controller.h"
 #include "chrome/browser/ash/crosapi/browser_data_migrator.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
 #include "chrome/browser/ash/login/app_mode/test/kiosk_base_test.h"
@@ -26,6 +27,7 @@
 #include "components/user_manager/fake_user_manager.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_launcher.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
 
@@ -157,10 +159,11 @@
   // Register the test app with `KioskAppManager` so that the `AccountId` can be
   // retrieved.
   PrepareAppLaunch();
-  KioskAppManager::App app;
-  CHECK(KioskAppManager::Get());
-  CHECK(KioskAppManager::Get()->GetApp(test_app_id(), &app));
-  CreateLacrosDirectoryForProfile(app.account_id);
+  absl::optional<KioskApp> app = KioskController::Get().GetAppById(
+      KioskAppId::ForChromeApp(test_app_id()));
+  ASSERT_TRUE(app.has_value());
+  ASSERT_TRUE(app->id().account_id.has_value());
+  CreateLacrosDirectoryForProfile(*app->id().account_id);
 
   base::test::TestFuture<void> waiter;
   ScopedBackMigratorRestartAttemptForTesting
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc b/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc
index b1f71e1..27f5909 100644
--- a/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc
+++ b/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc
@@ -14,6 +14,7 @@
 #include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
+#include "chrome/browser/ash/app_mode/kiosk_controller.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
 #include "chrome/browser/ash/crosapi/move_migrator.h"
 #include "chrome/browser/ash/login/app_mode/test/kiosk_base_test.h"
@@ -36,6 +37,7 @@
 #include "components/user_manager/fake_user_manager.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_launcher.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
 
@@ -434,13 +436,13 @@
   SetLacrosAvailability(
       ash::standalone_browser::LacrosAvailability::kUserChoice);
 
-  // Call this so that the test app is registered with `KioskAppManager` and
-  // thus the `AccountId` can be retrieved.
+  // Register app in `KioskController` so its `AccountId` can be retrieved.
   PrepareAppLaunch();
-  KioskAppManager::App app;
-  CHECK(KioskAppManager::Get());
-  CHECK(KioskAppManager::Get()->GetApp(test_app_id(), &app));
-  CreatePreferenceFileForProfile(app.account_id);
+  absl::optional<KioskApp> app = KioskController::Get().GetAppById(
+      KioskAppId::ForChromeApp(test_app_id()));
+  ASSERT_TRUE(app.has_value());
+  ASSERT_TRUE(app->id().account_id.has_value());
+  CreatePreferenceFileForProfile(app->id().account_id.value());
 
   base::RunLoop run_loop;
   ScopedRestartAttemptForTesting scoped_restart_attempt(
diff --git a/chrome/browser/ash/crosapi/browser_manager.cc b/chrome/browser/ash/crosapi/browser_manager.cc
index 450558d..f13837b 100644
--- a/chrome/browser/ash/crosapi/browser_manager.cc
+++ b/chrome/browser/ash/crosapi/browser_manager.cc
@@ -798,6 +798,10 @@
       first_non_pinned_tab_index, app_name, restore_window_id));
 }
 
+void BrowserManager::OpenProfileManager() {
+  PerformOrEnqueue(BrowserAction::OpenProfileManager());
+}
+
 bool BrowserManager::EnsureLaunch() {
   // This method can only ensure Lacros's launch if the user profile is already
   // initialized.
diff --git a/chrome/browser/ash/crosapi/browser_manager.h b/chrome/browser/ash/crosapi/browser_manager.h
index 3d3fdf0..96ffa4bf 100644
--- a/chrome/browser/ash/crosapi/browser_manager.h
+++ b/chrome/browser/ash/crosapi/browser_manager.h
@@ -248,6 +248,9 @@
       const std::string& app_name,
       int32_t restore_window_id);
 
+  // Opens the profile manager window in lacros-chrome.
+  void OpenProfileManager();
+
   // Ensures Lacros launches.
   // Returns true if Lacros could be launched, resumed, or is already in the
   // process of launching. Returns false if Lacros could not be launched.
diff --git a/chrome/browser/ash/crosapi/desk_profiles_ash.cc b/chrome/browser/ash/crosapi/desk_profiles_ash.cc
index ba6469d..0a8d604 100644
--- a/chrome/browser/ash/crosapi/desk_profiles_ash.cc
+++ b/chrome/browser/ash/crosapi/desk_profiles_ash.cc
@@ -30,9 +30,7 @@
 
 void DeskProfilesAsh::BindReceiver(
     mojo::PendingReceiver<mojom::DeskProfileObserver> pending_receiver) {
-  receiver_.Bind(std::move(pending_receiver));
-  receiver_.set_disconnect_handler(
-      base::BindOnce(&DeskProfilesAsh::OnDisconnect, base::Unretained(this)));
+  receivers_.Add(this, std::move(pending_receiver));
 }
 
 void DeskProfilesAsh::OnProfileUpsert(
@@ -87,8 +85,4 @@
                        }) != 0;
 }
 
-void DeskProfilesAsh::OnDisconnect() {
-  receiver_.reset();
-}
-
 }  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/desk_profiles_ash.h b/chrome/browser/ash/crosapi/desk_profiles_ash.h
index ef776bb..50a0c92c 100644
--- a/chrome/browser/ash/crosapi/desk_profiles_ash.h
+++ b/chrome/browser/ash/crosapi/desk_profiles_ash.h
@@ -11,7 +11,7 @@
 #include "base/observer_list.h"
 #include "chromeos/crosapi/mojom/desk_profiles.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
 namespace crosapi {
@@ -48,15 +48,12 @@
   // was known.
   bool RemoveProfile(uint64_t profile_id);
 
-  // Invoked if Lacros disconnects.
-  void OnDisconnect();
-
   // Cached list of profiles received from Lacros.
   std::vector<ash::LacrosProfileSummary> profiles_;
 
   base::ObserverList<Observer> observers_;
 
-  mojo::Receiver<mojom::DeskProfileObserver> receiver_{this};
+  mojo::ReceiverSet<mojom::DeskProfileObserver> receivers_;
 };
 
 }  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/input_method_test_interface_ash.h b/chrome/browser/ash/crosapi/input_method_test_interface_ash.h
index 5be1fa8..7ecab6b 100644
--- a/chrome/browser/ash/crosapi/input_method_test_interface_ash.h
+++ b/chrome/browser/ash/crosapi/input_method_test_interface_ash.h
@@ -34,7 +34,6 @@
 
   void Focus(const InputContext& input_context) override;
   void Blur() override {}
-  void OnTouch(ui::EventPointerType pointerType) override {}
   void Enable(const std::string& component_id) override {}
   void Disable() override {}
   void Reset() override {}
diff --git a/chrome/browser/ash/crosapi/print_job_info_idl_conversions.cc b/chrome/browser/ash/crosapi/print_job_info_idl_conversions.cc
index b98c928..02f5c02 100644
--- a/chrome/browser/ash/crosapi/print_job_info_idl_conversions.cc
+++ b/chrome/browser/ash/crosapi/print_job_info_idl_conversions.cc
@@ -20,28 +20,28 @@
 idl::ColorMode ColorModeProtoToIdl(proto::PrintSettings_ColorMode color_proto) {
   switch (color_proto) {
     case proto::PrintSettings_ColorMode_BLACK_AND_WHITE:
-      return idl::COLOR_MODE_BLACK_AND_WHITE;
+      return idl::ColorMode::kBlackAndWhite;
     case proto::PrintSettings_ColorMode_COLOR:
-      return idl::COLOR_MODE_COLOR;
+      return idl::ColorMode::kColor;
     default:
       NOTREACHED();
   }
-  return idl::COLOR_MODE_BLACK_AND_WHITE;
+  return idl::ColorMode::kBlackAndWhite;
 }
 
 idl::DuplexMode DuplexModeProtoToIdl(
     proto::PrintSettings_DuplexMode duplex_proto) {
   switch (duplex_proto) {
     case proto::PrintSettings_DuplexMode_ONE_SIDED:
-      return idl::DUPLEX_MODE_ONE_SIDED;
+      return idl::DuplexMode::kOneSided;
     case proto::PrintSettings_DuplexMode_TWO_SIDED_LONG_EDGE:
-      return idl::DUPLEX_MODE_TWO_SIDED_LONG_EDGE;
+      return idl::DuplexMode::kTwoSidedLongEdge;
     case proto::PrintSettings_DuplexMode_TWO_SIDED_SHORT_EDGE:
-      return idl::DUPLEX_MODE_TWO_SIDED_SHORT_EDGE;
+      return idl::DuplexMode::kTwoSidedShortEdge;
     default:
       NOTREACHED();
   }
-  return idl::DUPLEX_MODE_ONE_SIDED;
+  return idl::DuplexMode::kOneSided;
 }
 
 idl::MediaSize MediaSizeProtoToIdl(const proto::MediaSize& media_size_proto) {
@@ -67,43 +67,43 @@
   switch (print_job_source_proto) {
     case proto::PrintJobInfo_PrintJobSource_PRINT_PREVIEW:
     case proto::PrintJobInfo_PrintJobSource_PRINT_PREVIEW_INCOGNITO:
-      return idl::PRINT_JOB_SOURCE_PRINT_PREVIEW;
+      return idl::PrintJobSource::kPrintPreview;
     case proto::PrintJobInfo_PrintJobSource_ARC:
-      return idl::PRINT_JOB_SOURCE_ANDROID_APP;
+      return idl::PrintJobSource::kAndroidApp;
     case proto::PrintJobInfo_PrintJobSource_EXTENSION:
-      return idl::PRINT_JOB_SOURCE_EXTENSION;
+      return idl::PrintJobSource::kExtension;
     default:
       NOTREACHED();
   }
-  return idl::PRINT_JOB_SOURCE_PRINT_PREVIEW;
+  return idl::PrintJobSource::kPrintPreview;
 }
 
 idl::PrintJobStatus PrintJobStatusProtoToIdl(
     proto::PrintJobInfo_PrintJobStatus print_job_status_proto) {
   switch (print_job_status_proto) {
     case proto::PrintJobInfo_PrintJobStatus_FAILED:
-      return idl::PRINT_JOB_STATUS_FAILED;
+      return idl::PrintJobStatus::kFailed;
     case proto::PrintJobInfo_PrintJobStatus_CANCELED:
-      return idl::PRINT_JOB_STATUS_CANCELED;
+      return idl::PrintJobStatus::kCanceled;
     case proto::PrintJobInfo_PrintJobStatus_PRINTED:
-      return idl::PRINT_JOB_STATUS_PRINTED;
+      return idl::PrintJobStatus::kPrinted;
     default:
       NOTREACHED();
   }
-  return idl::PRINT_JOB_STATUS_FAILED;
+  return idl::PrintJobStatus::kFailed;
 }
 
 idl::PrinterSource PrinterSourceProtoToIdl(
     proto::Printer_PrinterSource printer_source_proto) {
   switch (printer_source_proto) {
     case proto::Printer_PrinterSource_USER:
-      return idl::PRINTER_SOURCE_USER;
+      return idl::PrinterSource::kUser;
     case proto::Printer_PrinterSource_POLICY:
-      return idl::PRINTER_SOURCE_POLICY;
+      return idl::PrinterSource::kPolicy;
     default:
       NOTREACHED();
   }
-  return idl::PRINTER_SOURCE_USER;
+  return idl::PrinterSource::kUser;
 }
 
 idl::Printer PrinterProtoToIdl(const proto::Printer& printer_proto) {
diff --git a/chrome/browser/ash/crosapi/print_job_info_idl_conversions_unittest.cc b/chrome/browser/ash/crosapi/print_job_info_idl_conversions_unittest.cc
index 6c2ba9d..82d3029f 100644
--- a/chrome/browser/ash/crosapi/print_job_info_idl_conversions_unittest.cc
+++ b/chrome/browser/ash/crosapi/print_job_info_idl_conversions_unittest.cc
@@ -71,18 +71,18 @@
 
   EXPECT_EQ(kId, print_job_info.id);
   EXPECT_EQ(kTitle, print_job_info.title);
-  EXPECT_EQ(idl::PRINT_JOB_SOURCE_PRINT_PREVIEW, print_job_info.source);
+  EXPECT_EQ(idl::PrintJobSource::kPrintPreview, print_job_info.source);
   EXPECT_EQ(absl::nullopt, print_job_info.source_id);
-  EXPECT_EQ(idl::PRINT_JOB_STATUS_FAILED, print_job_info.status);
+  EXPECT_EQ(idl::PrintJobStatus::kFailed, print_job_info.status);
   EXPECT_DOUBLE_EQ(static_cast<double>(kJobCreationTime),
                    print_job_info.creation_time);
   EXPECT_DOUBLE_EQ(static_cast<double>(kJobCompletionTime),
                    print_job_info.completion_time);
   EXPECT_EQ(kName, printer.name);
   EXPECT_EQ(kUri, printer.uri);
-  EXPECT_EQ(idl::PRINTER_SOURCE_POLICY, printer.source);
-  EXPECT_EQ(idl::COLOR_MODE_COLOR, settings.color);
-  EXPECT_EQ(idl::DUPLEX_MODE_ONE_SIDED, settings.duplex);
+  EXPECT_EQ(idl::PrinterSource::kPolicy, printer.source);
+  EXPECT_EQ(idl::ColorMode::kColor, settings.color);
+  EXPECT_EQ(idl::DuplexMode::kOneSided, settings.duplex);
   EXPECT_EQ(kCopies, settings.copies);
   EXPECT_EQ(kWidth, media_size.width);
   EXPECT_EQ(kHeight, media_size.height);
diff --git a/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc b/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc
index 8acfa23..496c357e 100644
--- a/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc
+++ b/chrome/browser/ash/crosapi/test_mojo_connection_manager_unittest.cc
@@ -104,6 +104,7 @@
   void NotifyPolicyFetchAttempt() override {}
   void UpdateKeepAlive(bool enabled) override {}
   void OpenForFullRestore(bool skip_crash_restore) override {}
+  void OpenProfileManager() override {}
   void UpdateComponentPolicy(
       base::flat_map<policy::PolicyNamespace, base::Value> policy) override {}
 
diff --git a/chrome/browser/ash/eche_app/eche_app_accessibility_provider_proxy.cc b/chrome/browser/ash/eche_app/eche_app_accessibility_provider_proxy.cc
index c77bd591..75abc31 100644
--- a/chrome/browser/ash/eche_app/eche_app_accessibility_provider_proxy.cc
+++ b/chrome/browser/ash/eche_app/eche_app_accessibility_provider_proxy.cc
@@ -107,6 +107,12 @@
             &EcheAppAccessibilityProviderProxy::OnAccessibilityStatusChanged,
             weak_ptr_factory_.GetWeakPtr()));
   }
+
+  // Send initial states.
+  if (accessibility_state_changed_callback_.has_value()) {
+    accessibility_state_changed_callback_->Run(IsAccessibilityEnabled());
+  }
+
   if (explore_by_touch_state_changed_callback_.has_value()) {
     explore_by_touch_state_changed_callback_->Run(
         accessibility_manager->IsSpokenFeedbackEnabled());
diff --git a/chrome/browser/ash/input_method/editor_helpers.cc b/chrome/browser/ash/input_method/editor_helpers.cc
new file mode 100644
index 0000000..111434f4
--- /dev/null
+++ b/chrome/browser/ash/input_method/editor_helpers.cc
@@ -0,0 +1,34 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+#include "base/containers/fixed_flat_set.h"
+#include "ui/gfx/range/range.h"
+
+namespace ash::input_method {
+
+constexpr auto striped_symbols =
+    base::MakeFixedFlatSet<char>({' ', '\t', '\n', '.', ','});
+
+size_t NonWhitespaceAndSymbolsLength(const std::u16string& text,
+                                     gfx::Range selection_range) {
+  size_t start = selection_range.start();
+  size_t end = selection_range.end();
+  if (start >= end || end > text.length()) {
+    return 0;
+  }
+
+  while (start < end && (striped_symbols.contains(text[start]) ||
+                         striped_symbols.contains(text[end - 1]))) {
+    if (striped_symbols.contains(text[start])) {
+      start++;
+    } else {
+      end--;
+    }
+  }
+
+  return end - start;
+}
+
+}  // namespace ash::input_method
diff --git a/chrome/browser/ash/input_method/editor_helpers.h b/chrome/browser/ash/input_method/editor_helpers.h
new file mode 100644
index 0000000..85862b5
--- /dev/null
+++ b/chrome/browser/ash/input_method/editor_helpers.h
@@ -0,0 +1,17 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_INPUT_METHOD_EDITOR_HELPERS_H_
+#define CHROME_BROWSER_ASH_INPUT_METHOD_EDITOR_HELPERS_H_
+
+#include <string>
+#include "ui/gfx/range/range.h"
+namespace ash::input_method {
+
+size_t NonWhitespaceAndSymbolsLength(const std::u16string& text,
+                                     gfx::Range selection_range);
+
+}  // namespace ash::input_method
+
+#endif  // CHROME_BROWSER_ASH_INPUT_METHOD_EDITOR_HELPERS_H_
diff --git a/chrome/browser/ash/input_method/editor_helpers_unittest.cc b/chrome/browser/ash/input_method/editor_helpers_unittest.cc
new file mode 100644
index 0000000..fe7aa88
--- /dev/null
+++ b/chrome/browser/ash/input_method/editor_helpers_unittest.cc
@@ -0,0 +1,105 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/input_method/editor_helpers.h"
+#include <cstddef>
+#include "content/public/test/test_browser_context.h"
+
+#include "ash/constants/ash_features.h"
+#include "base/test/gtest_util.h"
+#include "base/test/protobuf_matchers.h"
+#include "base/test/scoped_chromeos_version_info.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/test_future.h"
+#include "base/time/time.h"
+#include "chrome/test/base/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ash::input_method {
+namespace {
+
+using ::testing::TestWithParam;
+
+struct StripWhitespaceTestCase {
+  std::string test_name;
+
+  std::u16string text;
+  gfx::Range selection_range;
+
+  size_t stripped_length;
+};
+
+using StripWhitespaceTest = TestWithParam<StripWhitespaceTestCase>;
+
+INSTANTIATE_TEST_SUITE_P(
+    StripWhitespaceTests,
+    StripWhitespaceTest,
+    testing::ValuesIn<StripWhitespaceTestCase>({
+        {.test_name = "EmptyString",
+         .text = u"",
+         .selection_range = {0, 0},
+         .stripped_length = 0},
+        {.test_name = "SingleSpace",
+         .text = u" ",
+         .selection_range = {0, 1},
+         .stripped_length = 0},
+        {.test_name = "SingleLetter",
+         .text = u"a",
+         .selection_range = {0, 1},
+         .stripped_length = 1},
+        {.test_name = "PrependedWhitespace",
+         .text = u"    abc abc abc ",
+         .selection_range = {0, 4},
+         .stripped_length = 0},
+        {.test_name = "apendedWhitespace",
+         .text = u"    abc abc abc    ",
+         .selection_range = {15, 19},
+         .stripped_length = 0},
+        {.test_name = "WhitespaceAndSingleCharAtStart",
+         .text = u"    abc abc abc ",
+         .selection_range = {0, 5},
+         .stripped_length = 1},
+        {.test_name = "WhitespaceAndSingleCharAtEnd",
+         .text = u"    abc abc abc    ",
+         .selection_range = {14, 19},
+         .stripped_length = 1},
+        {.test_name = "WhitespaceRemovedFromStartButNotCenter",
+         .text = u"    abc abc abc ",
+         .selection_range = {1, 13},
+         .stripped_length = 9},
+        {.test_name = "WhitespaceRemovedFromEndButNotCenter",
+         .text = u"    abc abc abc   ",
+         .selection_range = {9, 16},
+         .stripped_length = 6},
+        {.test_name = "SingleWhitespaceAtEnd",
+         .text = u"    abc abc abc ",
+         .selection_range = {15, 16},
+         .stripped_length = 0},
+        {.test_name = "SingleCharAndWhitespaceAtEnd",
+         .text = u"    abc abc abc   ",
+         .selection_range = {14, 16},
+         .stripped_length = 1},
+        {.test_name = "SingleWhitespaceAtEndAndSingleChar",
+         .text = u"    abc abc abc   ",
+         .selection_range = {14, 18},
+         .stripped_length = 1},
+        {.test_name = "WhitespaceOnBothEnds",
+         .text = u"    abc abc abc   ",
+         .selection_range = {0, 18},
+         .stripped_length = 11},
+    }),
+    [](const testing::TestParamInfo<StripWhitespaceTest::ParamType>& info) {
+      return info.param.test_name;
+    });
+
+TEST_P(StripWhitespaceTest, TestEditorStripWhitespace) {
+  const StripWhitespaceTestCase& test_case = GetParam();
+
+  EXPECT_EQ(
+      NonWhitespaceAndSymbolsLength(test_case.text, test_case.selection_range),
+      test_case.stripped_length);
+}
+
+}  // namespace
+}  // namespace ash::input_method
diff --git a/chrome/browser/ash/input_method/editor_mediator.cc b/chrome/browser/ash/input_method/editor_mediator.cc
index bb209fe..3d70e0bd 100644
--- a/chrome/browser/ash/input_method/editor_mediator.cc
+++ b/chrome/browser/ash/input_method/editor_mediator.cc
@@ -13,6 +13,7 @@
 #include "base/check_op.h"
 #include "base/containers/contains.h"
 #include "base/containers/fixed_flat_set.h"
+#include "chrome/browser/ash/input_method/editor_helpers.h"
 #include "chrome/browser/ash/input_method/editor_metrics_enums.h"
 #include "chrome/browser/ash/input_method/editor_metrics_recorder.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -21,29 +22,6 @@
 #include "ui/base/ime/ash/ime_bridge.h"
 
 namespace ash::input_method {
-namespace {
-
-constexpr auto striped_symbols =
-    base::MakeFixedFlatSet<char>({' ', '\t', '\n', '.', ','});
-
-size_t NonWhitespaceAndSymbolsLength(const std::u16string& text,
-                                     gfx::Range selection_range) {
-  size_t start = selection_range.start();
-  while (start < selection_range.end() &&
-         striped_symbols.contains(text[start])) {
-    start++;
-  }
-
-  size_t end = selection_range.end();
-  while (end > selection_range.start() && end < text.length() &&
-         striped_symbols.contains(text[end])) {
-    end--;
-  }
-
-  return std::max(static_cast<int>(end) - static_cast<int>(start), 0);
-}
-
-}  // namespace
 
 EditorMediator::EditorMediator(Profile* profile, std::string_view country_code)
     : profile_(profile),
diff --git a/chrome/browser/ash/input_method/input_method_engine.cc b/chrome/browser/ash/input_method/input_method_engine.cc
index f104f84..8c84b1a 100644
--- a/chrome/browser/ash/input_method/input_method_engine.cc
+++ b/chrome/browser/ash/input_method/input_method_engine.cc
@@ -557,13 +557,6 @@
   observer_->OnBlur(active_component_id_, context_id);
 }
 
-void InputMethodEngine::OnTouch(ui::EventPointerType pointerType) {
-  if (!IsActive() || current_input_type_ == ui::TEXT_INPUT_TYPE_NONE)
-    return;
-
-  observer_->OnTouch(pointerType);
-}
-
 void InputMethodEngine::Enable(const std::string& component_id) {
   active_component_id_ = component_id;
   observer_->OnActivate(component_id);
diff --git a/chrome/browser/ash/input_method/input_method_engine.h b/chrome/browser/ash/input_method/input_method_engine.h
index 7c062d4..eb5a61c 100644
--- a/chrome/browser/ash/input_method/input_method_engine.h
+++ b/chrome/browser/ash/input_method/input_method_engine.h
@@ -234,7 +234,6 @@
   // TextInputMethod overrides.
   void Focus(const TextInputMethod::InputContext& input_context) override;
   void Blur() override;
-  void OnTouch(ui::EventPointerType pointerType) override;
   void Enable(const std::string& component_id) override;
   void Disable() override;
   void Reset() override;
diff --git a/chrome/browser/ash/input_method/input_method_engine_observer.h b/chrome/browser/ash/input_method/input_method_engine_observer.h
index 2bad7274..25cb75aa 100644
--- a/chrome/browser/ash/input_method/input_method_engine_observer.h
+++ b/chrome/browser/ash/input_method/input_method_engine_observer.h
@@ -51,11 +51,6 @@
                        int context_id,
                        const TextInputMethod::InputContext& context) = 0;
 
-  // Called on a touch within a text field. Allows for features like changing
-  // virtual keyboard layout based on touch type after onfocus (since
-  // subsequent touches within the same input field do not send onfocus),
-  virtual void OnTouch(ui::EventPointerType pointerType) = 0;
-
   // Called when a text field loses focus, and will no longer generate events.
   virtual void OnBlur(const std::string& engine_id, int context_id) = 0;
 
diff --git a/chrome/browser/ash/input_method/mock_input_method_engine.cc b/chrome/browser/ash/input_method/mock_input_method_engine.cc
index b23f55c..719bc28 100644
--- a/chrome/browser/ash/input_method/mock_input_method_engine.cc
+++ b/chrome/browser/ash/input_method/mock_input_method_engine.cc
@@ -16,8 +16,6 @@
 void MockInputMethodEngine::Focus(
     const TextInputMethod::InputContext& input_context) {}
 
-void MockInputMethodEngine::OnTouch(ui::EventPointerType pointerType) {}
-
 void MockInputMethodEngine::Blur() {}
 
 void MockInputMethodEngine::Enable(const std::string& component_id) {
diff --git a/chrome/browser/ash/input_method/mock_input_method_engine.h b/chrome/browser/ash/input_method/mock_input_method_engine.h
index 9ed34d8..e114e43 100644
--- a/chrome/browser/ash/input_method/mock_input_method_engine.h
+++ b/chrome/browser/ash/input_method/mock_input_method_engine.h
@@ -33,7 +33,6 @@
   // TextInputMethod overrides.
   void Focus(const InputContext& input_context) override;
   void Blur() override;
-  void OnTouch(ui::EventPointerType pointerType) override;
   void Enable(const std::string& component_id) override;
   void Disable() override;
   void Reset() override;
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 11c4513..4c602030 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
@@ -953,11 +953,6 @@
   SendSurroundingTextToNativeMojoEngine(last_surrounding_text_);
 }
 
-void NativeInputMethodEngineObserver::OnTouch(
-    ui::EventPointerType pointerType) {
-  ime_base_observer_->OnTouch(pointerType);
-}
-
 void NativeInputMethodEngineObserver::OnBlur(const std::string& engine_id,
                                              int context_id) {
   // Always hide the candidates window when there's no focus.
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 0b79afb..30313b14 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
@@ -63,7 +63,6 @@
   void OnFocus(const std::string& engine_id,
                int context_id,
                const TextInputMethod::InputContext& context) override;
-  void OnTouch(ui::EventPointerType pointerType) override;
   void OnBlur(const std::string& engine_id, int context_id) override;
   void OnKeyEvent(const std::string& engine_id,
                   const ui::KeyEvent& event,
diff --git a/chrome/browser/ash/input_method/stub_input_method_engine_observer.h b/chrome/browser/ash/input_method/stub_input_method_engine_observer.h
index fea932da26..ac1c819 100644
--- a/chrome/browser/ash/input_method/stub_input_method_engine_observer.h
+++ b/chrome/browser/ash/input_method/stub_input_method_engine_observer.h
@@ -23,7 +23,6 @@
   void OnFocus(const std::string& engine_id,
                int context_id,
                const TextInputMethod::InputContext& context) override {}
-  void OnTouch(ui::EventPointerType pointerType) override {}
   void OnBlur(const std::string& engine_id, int context_id) override {}
   void OnKeyEvent(const std::string& engine_id,
                   const ui::KeyEvent& event,
diff --git a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
index 9195fba..21a2f69 100644
--- a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
+++ b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/ash/app_mode/app_launch_utils.h"
 #include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_service.h"
+#include "chrome/browser/ash/app_mode/kiosk_app.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_launcher.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_types.h"
@@ -54,6 +55,8 @@
 #include "chrome/common/chrome_features.h"
 #include "components/crash/core/common/crash_key.h"
 #include "content/public/browser/network_service_instance.h"
+#include "ui/gfx/image/image_skia.h"
+#include "url/gurl.h"
 
 namespace ash {
 namespace {
@@ -324,7 +327,7 @@
 
   network_ui_controller_->Start();
 
-  splash_screen_view_->Show(GetAppData());
+  splash_screen_view_->Show(GetSplashScreenAppData());
 
   splash_wait_timer_.Start(FROM_HERE, GetSplashScreenMinTime(),
                            base::BindOnce(&KioskLaunchController::OnTimerFire,
@@ -460,39 +463,21 @@
   chrome::AttemptUserExit();
 }
 
-KioskAppManagerBase::App KioskLaunchController::GetAppData() {
-  DCHECK(kiosk_app_id_.account_id.has_value());
-  switch (kiosk_app_id_.type) {
-    case KioskAppType::kChromeApp: {
-      KioskAppManagerBase::App app;
-      if (KioskAppManager::Get()->GetApp(*kiosk_app_id_.app_id, &app)) {
-        return app;
-      }
-      break;
-    }
-    case KioskAppType::kArcApp: {
-      const ArcKioskAppData* arc_app =
-          ArcKioskAppManager::Get()->GetAppByAccountId(
-              *kiosk_app_id_.account_id);
-      if (arc_app) {
-        return KioskAppManagerBase::App(*arc_app);
-      }
-      break;
-    }
-    case KioskAppType::kWebApp: {
-      const WebKioskAppData* web_app =
-          WebKioskAppManager::Get()->GetAppByAccountId(
-              *kiosk_app_id_.account_id);
-      if (web_app) {
-        return WebKioskAppManager::CreateAppByData(*web_app);
-      }
-      break;
-    }
-  }
+AppLaunchSplashScreenView::Data
+KioskLaunchController::GetSplashScreenAppData() {
+  // TODO(b/306117645) upgrade to CHECK.
+  DUMP_WILL_BE_CHECK(kiosk_app_id_.account_id.has_value());
 
-  LOG(WARNING) << "Cannot get a valid kiosk app. App type: "
-               << (int)kiosk_app_id_.type;
-  return KioskAppManagerBase::App();
+  absl::optional<KioskApp> app =
+      KioskController::Get().GetAppById(kiosk_app_id_);
+  DUMP_WILL_BE_CHECK(app.has_value());
+
+  if (!app.has_value()) {
+    return AppLaunchSplashScreenView::Data(
+        /*name=*/std::string(), /*icon=*/gfx::ImageSkia(), /*url=*/GURL());
+  }
+  return AppLaunchSplashScreenView::Data(app->name(), app->icon(),
+                                         /*url=*/app->url().value_or(GURL()));
 }
 
 void KioskLaunchController::CleanUp() {
@@ -549,7 +534,7 @@
   splash_screen_view_->UpdateAppLaunchState(
       AppLaunchSplashScreenView::AppLaunchState::kInstallingApplication);
 
-  splash_screen_view_->Show(GetAppData());
+  splash_screen_view_->Show(GetSplashScreenAppData());
 }
 
 void KioskLaunchController::OnAppPrepared() {
@@ -563,7 +548,7 @@
 
   splash_screen_view_->UpdateAppLaunchState(
       AppLaunchSplashScreenView::AppLaunchState::kInstallingExtension);
-  splash_screen_view_->Show(GetAppData());
+  splash_screen_view_->Show(GetSplashScreenAppData());
 
   force_install_observer_ = std::make_unique<app_mode::ForceInstallObserver>(
       profile_,
@@ -632,7 +617,7 @@
   splash_screen_view_->UpdateAppLaunchState(
       AppLaunchSplashScreenView::AppLaunchState::
           kWaitingAppWindowInstallFailed);
-  splash_screen_view_->Show(GetAppData());
+  splash_screen_view_->Show(GetSplashScreenAppData());
   if (launch_on_install_ || g_skip_splash_wait_for_testing) {
     LaunchApp();
   }
@@ -661,7 +646,7 @@
 
   splash_screen_view_->UpdateAppLaunchState(
       AppLaunchSplashScreenView::AppLaunchState::kWaitingAppWindow);
-  splash_screen_view_->Show(GetAppData());
+  splash_screen_view_->Show(GetSplashScreenAppData());
 
   if (launch_on_install_ || g_skip_splash_wait_for_testing) {
     LaunchApp();
@@ -674,7 +659,7 @@
   if (splash_screen_view_) {
     splash_screen_view_->UpdateAppLaunchState(
         AppLaunchSplashScreenView::AppLaunchState::kWaitingAppWindow);
-    splash_screen_view_->Show(GetAppData());
+    splash_screen_view_->Show(GetSplashScreenAppData());
   }
   session_manager::SessionManager::Get()->SessionStarted();
 }
@@ -697,7 +682,7 @@
 void KioskLaunchController::OnAppDataUpdated() {
   // Invokes Show() to update the app title and icon.
   if (splash_screen_view_) {
-    splash_screen_view_->Show(GetAppData());
+    splash_screen_view_->Show(GetSplashScreenAppData());
   }
 }
 
@@ -749,7 +734,7 @@
   if (splash_screen_view_) {
     splash_screen_view_->UpdateAppLaunchState(
         AppLaunchSplashScreenView::AppLaunchState::kPreparingProfile);
-    splash_screen_view_->Show(GetAppData());
+    splash_screen_view_->Show(GetSplashScreenAppData());
   }
 
   InitializeLauncher();
diff --git a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h
index f21ab15..785e4c6 100644
--- a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h
+++ b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h
@@ -179,7 +179,8 @@
   void OnOldEncryptionDetected(
       std::unique_ptr<UserContext> user_context) override;
 
-  KioskAppManagerBase::App GetAppData();
+  // Returns the `Data` struct used to populate the splash screen.
+  AppLaunchSplashScreenView::Data GetSplashScreenAppData();
 
   void HandleWebAppInstallFailed();
 
diff --git a/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc b/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc
index 477d6f3..7cfd549 100644
--- a/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc
+++ b/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc
@@ -9,7 +9,9 @@
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
 #include "ash/public/cpp/login_accelerators.h"
+#include "base/check_deref.h"
 #include "base/functional/bind.h"
+#include "base/logging.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
@@ -18,10 +20,13 @@
 #include "base/test/scoped_command_line.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_future.h"
+#include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/fake_kiosk_app_launcher.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_launch_error.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_launcher.h"
+#include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_types.h"
+#include "chrome/browser/ash/app_mode/kiosk_controller.h"
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
 #include "chrome/browser/ash/crosapi/crosapi_ash.h"
 #include "chrome/browser/ash/crosapi/crosapi_manager.h"
@@ -130,6 +135,21 @@
   base::WeakPtrFactory<FakeNetworkMonitor> weak_ptr_factory_{this};
 };
 
+// Helper class to own `KioskController` and the Kiosk managers it depends on.
+class KioskControllerHolder {
+ public:
+  KioskControllerHolder()
+      : kiosk_controller(web_kiosk_app_manager_,
+                         chrome_app_kiosk_app_manager_,
+                         arc_kiosk_app_manager_) {}
+  ~KioskControllerHolder() = default;
+
+  WebKioskAppManager web_kiosk_app_manager_;
+  KioskAppManager chrome_app_kiosk_app_manager_;
+  ArcKioskAppManager arc_kiosk_app_manager_;
+  KioskController kiosk_controller;
+};
+
 }  // namespace
 
 using NetworkUIState = NetworkUiController::NetworkUIState;
@@ -202,7 +222,7 @@
   void TearDown() override {
     extensions::ExtensionServiceTestBase::TearDown();
 
-    kiosk_app_manager_.reset();
+    kiosk_controller_holder_.reset();
 
     policy::BrowserPolicyConnectorBase::SetPolicyServiceForTesting(nullptr);
   }
@@ -285,9 +305,9 @@
     AccountId account_id(AccountId::FromUserEmail(email));
     kiosk_app_id_ = KioskAppId::ForWebApp(account_id);
 
-    kiosk_app_manager_ = std::make_unique<WebKioskAppManager>();
-    kiosk_app_manager_->AddAppForTesting(kiosk_app_id_.account_id.value(),
-                                         GURL(kInstallUrl));
+    kiosk_controller_holder_ = std::make_unique<KioskControllerHolder>();
+    WebKioskAppManager::Get()->AddAppForTesting(
+        kiosk_app_id_.account_id.value(), GURL(kInstallUrl));
   }
 
   std::unique_ptr<KioskAppLauncher> BuildFakeKioskAppLauncher(
@@ -304,7 +324,7 @@
   session_manager::SessionManager session_manager_;
   std::unique_ptr<ChromeKeyboardControllerClientTestHelper>
       keyboard_controller_client_;
-  std::unique_ptr<WebKioskAppManager> kiosk_app_manager_;
+  std::unique_ptr<KioskControllerHolder> kiosk_controller_holder_;
 
   std::unique_ptr<base::AutoReset<absl::optional<bool>>>
       can_configure_network_for_testing_;
@@ -326,8 +346,7 @@
 
 TEST_F(KioskLaunchControllerTest, StartShouldShowAppDataOnSplashScreen) {
   controller().Start(kiosk_app_id(), /*auto_launch=*/false);
-
-  EXPECT_EQ(view().last_app_data().url, GURL(kInstallUrl));
+  EXPECT_EQ(view().last_data().url, GURL(kInstallUrl));
 }
 
 TEST_F(KioskLaunchControllerTest, ProfileLoadedShouldInitializeLauncher) {
@@ -930,9 +949,9 @@
   }
 
   void SetUpKioskAppInAppManager() {
-    kiosk_app_manager_ = std::make_unique<WebKioskAppManager>();
-    kiosk_app_manager_->AddAppForTesting(kiosk_app_id_.account_id.value(),
-                                         GURL(kInstallUrl));
+    kiosk_controller_holder_ = std::make_unique<KioskControllerHolder>();
+    WebKioskAppManager::Get()->AddAppForTesting(
+        kiosk_app_id_.account_id.value(), GURL(kInstallUrl));
   }
 
   std::unique_ptr<KioskAppLauncher> BuildFakeKioskAppLauncher(
@@ -959,7 +978,7 @@
 
   std::unique_ptr<ChromeKeyboardControllerClientTestHelper>
       keyboard_controller_client_;
-  std::unique_ptr<WebKioskAppManager> kiosk_app_manager_;
+  std::unique_ptr<KioskControllerHolder> kiosk_controller_holder_;
 
   std::unique_ptr<base::AutoReset<absl::optional<bool>>>
       can_configure_network_for_testing_;
diff --git a/chrome/browser/ash/login/screens/osauth/base_osauth_setup_screen.cc b/chrome/browser/ash/login/screens/osauth/base_osauth_setup_screen.cc
new file mode 100644
index 0000000..8f00634
--- /dev/null
+++ b/chrome/browser/ash/login/screens/osauth/base_osauth_setup_screen.cc
@@ -0,0 +1,152 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/login/screens/osauth/base_osauth_setup_screen.h"
+
+#include <memory>
+#include <utility>
+
+#include "ash/constants/ash_features.h"
+#include "base/check_op.h"
+#include "base/functional/bind.h"
+#include "base/functional/callback_helpers.h"
+#include "chrome/browser/ash/login/quick_unlock/quick_unlock_factory.h"
+#include "chrome/browser/ash/login/quick_unlock/quick_unlock_storage.h"
+#include "chrome/browser/ash/login/screens/base_screen.h"
+#include "chrome/browser/ash/login/wizard_context.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chromeos/ash/components/osauth/public/auth_session_storage.h"
+
+namespace ash {
+
+BaseOSAuthSetupScreen::BaseOSAuthSetupScreen(OobeScreenId screen_id,
+                                             OobeScreenPriority screen_priority)
+    : BaseScreen(screen_id, screen_priority) {}
+
+BaseOSAuthSetupScreen::~BaseOSAuthSetupScreen() = default;
+
+void BaseOSAuthSetupScreen::HideImpl() {
+  if (!ash::features::ShouldUseAuthSessionStorage()) {
+    StoreQuickUnlockContext();
+  }
+  session_refresher_.reset();
+}
+
+void BaseOSAuthSetupScreen::EnsureQuickUnlockToken() {
+  CHECK(!ash::features::ShouldUseAuthSessionStorage());
+  if (quick_unlock_token_) {
+    return;
+  }
+  CHECK(context()->extra_factors_auth_session);
+
+  quick_unlock::QuickUnlockStorage* quick_unlock_storage =
+      quick_unlock::QuickUnlockFactory::GetForProfile(
+          ProfileManager::GetActiveUserProfile());
+  CHECK(quick_unlock_storage);
+  quick_unlock_token_ = quick_unlock_storage->CreateAuthToken(
+      *context()->extra_factors_auth_session);
+}
+
+void BaseOSAuthSetupScreen::StoreQuickUnlockContext() {
+  CHECK(!ash::features::ShouldUseAuthSessionStorage());
+  if (!quick_unlock_token_) {
+    return;
+  }
+  quick_unlock::QuickUnlockStorage* quick_unlock_storage =
+      quick_unlock::QuickUnlockFactory::GetForProfile(
+          ProfileManager::GetActiveUserProfile());
+  if (!quick_unlock_storage->GetUserContext(*quick_unlock_token_)) {
+    // Context already expired
+    quick_unlock_token_ = absl::nullopt;
+    return;
+  }
+  context()->extra_factors_auth_session = std::make_unique<UserContext>(
+      *quick_unlock_storage->GetUserContext(*quick_unlock_token_));
+  quick_unlock_storage->ReplaceUserContext(*quick_unlock_token_,
+                                           std::make_unique<UserContext>());
+  quick_unlock_token_ = absl::nullopt;
+}
+
+AuthProofToken BaseOSAuthSetupScreen::GetToken() {
+  if (!ash::features::ShouldUseAuthSessionStorage()) {
+    EnsureQuickUnlockToken();
+    return *quick_unlock_token_;
+  }
+  CHECK(context()->extra_factors_token.has_value());
+  return *(context()->extra_factors_token);
+}
+
+void BaseOSAuthSetupScreen::KeepAliveAuthSession() {
+  if (!ash::features::ShouldUseAuthSessionStorage()) {
+    return;
+  }
+  session_refresher_ = AuthSessionStorage::Get()->KeepAlive(GetToken());
+}
+
+void BaseOSAuthSetupScreen::InspectContextAndContinue(
+    InspectContextCallback inspect_callback,
+    base::OnceClosure continuation) {
+  if (!ash::features::ShouldUseAuthSessionStorage()) {
+    EnsureQuickUnlockToken();
+    quick_unlock::QuickUnlockStorage* quick_unlock_storage =
+        quick_unlock::QuickUnlockFactory::GetForProfile(
+            ProfileManager::GetActiveUserProfile());
+    UserContext* context =
+        quick_unlock_storage->GetUserContext(*quick_unlock_token_);
+    std::move(inspect_callback).Run(context);
+    if (context) {
+      std::move(continuation).Run();
+    }
+    return;
+  }
+  auto token = GetToken();
+  CHECK(AuthSessionStorage::Get()->IsValid(token));
+  AuthSessionStorage::Get()->BorrowAsync(
+      FROM_HERE, token,
+      base::BindOnce(
+          &BaseOSAuthSetupScreen::InspectContextAndContinueWithContext,
+          weak_ptr_factory_.GetWeakPtr(), std::move(inspect_callback),
+          std::move(continuation)));
+}
+
+void BaseOSAuthSetupScreen::InspectContextAndContinueWithContext(
+    InspectContextCallback inspect_callback,
+    base::OnceClosure continuation,
+    std::unique_ptr<UserContext> user_context) {
+  std::move(inspect_callback).Run(user_context.get());
+  if (!user_context) {
+    return;
+  }
+  AuthSessionStorage::Get()->Return(GetToken(), std::move(user_context));
+  std::move(continuation).Run();
+}
+
+void BaseOSAuthSetupScreen::EstablishKnowledgeFactorGuard(
+    base::OnceClosure continuation) {
+  auto split_continuation = base::SplitOnceCallback(std::move(continuation));
+  InspectContextAndContinue(
+      base::BindOnce(&BaseOSAuthSetupScreen::CheckForKnowledgeFactorPresence,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     std::move(split_continuation.first)),
+      std::move(split_continuation.second));
+}
+
+void BaseOSAuthSetupScreen::CheckForKnowledgeFactorPresence(
+    base::OnceClosure continuation,
+    UserContext* context) {
+  if (!context) {
+    std::move(continuation).Run();
+    return;
+  }
+  // Until we support PIN-only setups, check only for Password factor type.
+  bool has_knowledge_factor =
+      context->GetAuthFactorsConfiguration().HasConfiguredFactor(
+          cryptohome::AuthFactorType::kPassword);
+
+  if (!has_knowledge_factor) {
+    KeepAliveAuthSession();
+  }
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/login/screens/osauth/base_osauth_setup_screen.h b/chrome/browser/ash/login/screens/osauth/base_osauth_setup_screen.h
new file mode 100644
index 0000000..c59e6420
--- /dev/null
+++ b/chrome/browser/ash/login/screens/osauth/base_osauth_setup_screen.h
@@ -0,0 +1,82 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_LOGIN_SCREENS_OSAUTH_BASE_OSAUTH_SETUP_SCREEN_H_
+#define CHROME_BROWSER_ASH_LOGIN_SCREENS_OSAUTH_BASE_OSAUTH_SETUP_SCREEN_H_
+
+#include <string>
+
+#include "base/functional/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/ash/login/screens/base_screen.h"
+#include "chromeos/ash/components/osauth/public/common_types.h"
+
+namespace ash {
+
+class UserContext;
+class ScopedSessionRefresher;
+// Generic base class for Screens that need to interact with `cryptohomed`
+// to properly configure user's authentication on the device.
+// See protected methods.
+
+class BaseOSAuthSetupScreen : public BaseScreen {
+  using InspectContextCallback = base::OnceCallback<void(UserContext*)>;
+
+  BaseOSAuthSetupScreen(OobeScreenId screen_id,
+                        OobeScreenPriority screen_priority);
+
+  BaseOSAuthSetupScreen(const BaseOSAuthSetupScreen&) = delete;
+  BaseOSAuthSetupScreen& operator=(const BaseOSAuthSetupScreen&) = delete;
+
+  ~BaseOSAuthSetupScreen() override;
+
+ protected:
+  // In case when QuickUnlockStorage is used, would ensure
+  // that any modifications to UserContext happened while screen
+  // was show are correctly stored in WizardContext.
+  // Resets AuthSession refresher if it was requested.
+  void HideImpl() override;
+
+  // Convenient way to obtain token associated with UserContext.
+  AuthProofToken GetToken();
+
+  // Convenient way to obtain context for synchronous inspection/modification,
+  // and proceeding once context is stored in Storage.
+  // If context is invalidate by the time of request, `inspect_callback` would
+  // be called with `nullptr` as parameter, and `continuation` would NOT be
+  // called.
+  void InspectContextAndContinue(InspectContextCallback inspect_callback,
+                                 base::OnceClosure continuation);
+
+  // Obtain and store `ScopedSessionRefresher`. Refresher would be cleared upon
+  // screen exit. Does nothing if UseAuthSessionStorage flag is disabled.
+  void KeepAliveAuthSession();
+
+  // Inspects UserContext and establishes Session refresher if there is
+  // no knowledge factor established yet.
+  // TODO(b/271249180): once notification for session expiration is implemented,
+  // register for such notification if there is a knowledge factor.
+  void EstablishKnowledgeFactorGuard(base::OnceClosure continuation);
+
+ private:
+  void EnsureQuickUnlockToken();
+  void InspectContextAndContinueWithContext(
+      InspectContextCallback inspect_callback,
+      base::OnceClosure continuation,
+      std::unique_ptr<UserContext> user_context);
+
+  void StoreQuickUnlockContext();
+  void CheckForKnowledgeFactorPresence(base::OnceClosure continuation,
+                                       UserContext* context);
+
+  absl::optional<std::string> quick_unlock_token_;
+  std::unique_ptr<ScopedSessionRefresher> session_refresher_;
+
+  base::WeakPtrFactory<BaseOSAuthSetupScreen> weak_ptr_factory_{this};
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_OSAUTH_BASE_OSAUTH_SETUP_SCREEN_H_
diff --git a/chrome/browser/ash/login/ui/login_feedback_browsertest.cc b/chrome/browser/ash/login/ui/login_feedback_browsertest.cc
index 827252ff..d1cc005d2 100644
--- a/chrome/browser/ash/login/ui/login_feedback_browsertest.cc
+++ b/chrome/browser/ash/login/ui/login_feedback_browsertest.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/ui/webui/ash/system_web_dialog_delegate.h"
 #include "chrome/browser/ui/webui/feedback/feedback_dialog.h"
 #include "content/public/test/browser_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
 namespace {
@@ -105,6 +106,10 @@
 }
 
 void TestFeedback() {
+  // TODO(http://b/309467654): clean up obsolete code.
+  if (ash::features::IsOsFeedbackDialogEnabled()) {
+    GTEST_SKIP();
+  }
   Profile* const profile = ProfileHelper::GetSigninProfile();
   auto login_feedback = std::make_unique<ash::LoginFeedback>(profile);
 
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_time_of_day_browsertest.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_time_of_day_browsertest.cc
index b117065..9d15178 100644
--- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_time_of_day_browsertest.cc
+++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_time_of_day_browsertest.cc
@@ -14,13 +14,13 @@
 #include "ash/public/cpp/wallpaper/wallpaper_info.h"
 #include "ash/public/cpp/wallpaper/wallpaper_types.h"
 #include "ash/shell.h"
-#include "ash/style/dark_light_mode_controller_impl.h"
 #include "ash/system/geolocation/geolocation_controller.h"
 #include "ash/system/geolocation/test_geolocation_url_loader_factory.h"
 #include "ash/system/scheduled_feature/scheduled_feature.h"
 #include "ash/wallpaper/test_wallpaper_image_downloader.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
 #include "ash/wallpaper/wallpaper_controller_test_api.h"
+#include "ash/wallpaper/wallpaper_time_of_day_scheduler.h"
 #include "ash/wallpaper/wallpaper_utils/wallpaper_online_variant_utils.h"
 #include "ash/webui/personalization_app/personalization_app_url_constants.h"
 #include "base/functional/callback_forward.h"
@@ -150,13 +150,14 @@
     test_chrome_webui_controller_factory_.AddFactoryOverride(
         kChromeUIPersonalizationAppHost, &test_webui_provider_);
 
-    auto* dark_light_controller = Shell::Get()->dark_light_mode_controller();
+    time_of_day_scheduler_ = Shell::Get()
+                                 ->wallpaper_controller()
+                                 ->time_of_day_scheduler_for_testing();
     // Disable any running timers to set a fake clock.
-    dark_light_controller->SetAutoScheduleEnabled(false);
-    dark_light_controller->SetClockForTesting(this);
+    time_of_day_scheduler_->SetScheduleType(ScheduleType::kNone);
+    time_of_day_scheduler_->SetClockForTesting(this);
     // Re-enable auto schedule and sun timer.
-    dark_light_controller->SetAutoScheduleEnabled(true);
-    dark_light_controller->SetScheduleType(ScheduleType::kSunsetToSunrise);
+    time_of_day_scheduler_->SetScheduleType(ScheduleType::kSunsetToSunrise);
 
     auto* geolocation_controller = GeolocationController::Get();
     geolocation_controller->SetClockForTesting(this);
@@ -178,6 +179,7 @@
     SystemWebAppBrowserTestBase::TearDownOnMainThread();
 
     test_geolocation_url_loader_factory_ = nullptr;
+    time_of_day_scheduler_ = nullptr;
   }
 
   content::WebContents* LaunchAppAtWallpaperSubpage(Browser** browser) {
@@ -218,16 +220,19 @@
   bool FastForwardBy(base::TimeDelta time_delta) {
     clock_.Advance(time_delta);
     tick_clock_.Advance(time_delta);
-    auto* dark_light_mode_controller = DarkLightModeControllerImpl::Get();
     const bool checkpoint_should_change =
-        dark_light_mode_controller->timer()->IsRunning() &&
-        dark_light_mode_controller->timer()->desired_run_time() < NowTicks();
+        time_of_day_scheduler_->timer()->IsRunning() &&
+        time_of_day_scheduler_->timer()->desired_run_time() < NowTicks();
     if (checkpoint_should_change) {
-      dark_light_mode_controller->timer()->FireNow();
+      time_of_day_scheduler_->timer()->FireNow();
     }
     return checkpoint_should_change;
   }
 
+  ScheduleCheckpoint GetCurrentCheckpoint() {
+    return time_of_day_scheduler_->current_checkpoint();
+  }
+
  private:
   std::vector<base::Time> GenerateTimesToTest() {
     const auto& timestamps = GetParam().timestamps_to_test;
@@ -242,6 +247,7 @@
   base::SimpleTestClock clock_;
   base::SimpleTestTickClock tick_clock_;
   raw_ptr<TestGeolocationUrlLoaderFactory> test_geolocation_url_loader_factory_;
+  raw_ptr<WallpaperTimeOfDayScheduler> time_of_day_scheduler_;
   TestChromeWebUIControllerFactory test_chrome_webui_controller_factory_;
   TestPersonalizationAppWebUIProvider test_webui_provider_;
   content::ScopedWebUIControllerFactoryRegistration
@@ -310,26 +316,19 @@
     loop.Run();
   }
 
-  auto* dark_light_controller = Shell::Get()->dark_light_mode_controller();
   auto* wallpaper_controller = Shell::Get()->wallpaper_controller();
 
-  ASSERT_TRUE(dark_light_controller->GetAutoScheduleEnabled())
-      << "Time of day wallpaper needs auto schedule enabled";
-  ASSERT_EQ(ScheduleType::kSunsetToSunrise,
-            dark_light_controller->GetScheduleType())
-      << "Time of day wallpaper needs sunrise/sunset to change automatically";
   ASSERT_EQ(WallpaperType::kOnline, wallpaper_controller->GetWallpaperType())
       << "Time of day wallpaper expected";
   ASSERT_EQ(wallpaper_handlers::MockBackdropImageInfoFetcher::kTimeOfDayUnitId,
             wallpaper_controller->GetActiveUserWallpaperInfo()->unit_id.value())
       << "Time of day wallpaper unit id set as wallpaper";
 
-  std::vector<ScheduleCheckpoint> all_checkpoints(
-      {dark_light_controller->current_checkpoint()});
+  std::vector<ScheduleCheckpoint> all_checkpoints({GetCurrentCheckpoint()});
   std::vector<backdrop::Image::ImageType> all_image_types = {
       FirstValidVariant(
           wallpaper_controller->GetActiveUserWallpaperInfo()->variants,
-          dark_light_controller->current_checkpoint())
+          GetCurrentCheckpoint())
           ->type};
 
   for (const auto& checkpoint_time : TimesToIterate()) {
@@ -340,7 +339,7 @@
       loop.Run();
     }
 
-    all_checkpoints.push_back(dark_light_controller->current_checkpoint());
+    all_checkpoints.push_back(GetCurrentCheckpoint());
 
     auto current_wallpaper_info =
         wallpaper_controller->GetActiveUserWallpaperInfo().value();
@@ -348,10 +347,9 @@
         wallpaper_handlers::MockBackdropImageInfoFetcher::kTimeOfDayUnitId,
         current_wallpaper_info.unit_id.value())
         << "WallpaperInfo still has time of day unit_id";
-    all_image_types.push_back(
-        FirstValidVariant(current_wallpaper_info.variants,
-                          dark_light_controller->current_checkpoint())
-            ->type);
+    all_image_types.push_back(FirstValidVariant(current_wallpaper_info.variants,
+                                                GetCurrentCheckpoint())
+                                  ->type);
   }
 
   EXPECT_EQ(ExpectedScheduleCheckpoints(), all_checkpoints);
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index ff01e3e8..d747d2b 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -3125,9 +3125,6 @@
   for (content::BrowsingDataRemover::DataType test_data_type : test_cases) {
     {
       FederatedIdentityPermissionContext federated_context(GetProfile());
-      federated_context.GrantActiveSession(rp_origin, idp_origin, account_id);
-      ASSERT_TRUE(federated_context.HasActiveSession(rp_origin, idp_origin,
-                                                     account_id));
 
       federated_context.GrantSharingPermission(rp_origin, rp_embedder_origin,
                                                idp_origin, account_id);
@@ -3153,8 +3150,6 @@
       // ObjectPermissionContextBase cache.
       FederatedIdentityPermissionContext federated_context(GetProfile());
 
-      EXPECT_FALSE(federated_context.HasActiveSession(rp_origin, idp_origin,
-                                                      account_id));
       EXPECT_FALSE(federated_context.HasSharingPermission(
           rp_origin, rp_embedder_origin, idp_origin, account_id));
 
diff --git a/chrome/browser/cart/BUILD.gn b/chrome/browser/cart/BUILD.gn
index 6cef247..98c5b2e 100644
--- a/chrome/browser/cart/BUILD.gn
+++ b/chrome/browser/cart/BUILD.gn
@@ -8,5 +8,4 @@
   sources = [ "chrome_cart.mojom" ]
   public_deps = [ "//url/mojom:url_mojom_gurl" ]
   webui_module_path = "/"
-  use_typescript_sources = true
 }
diff --git a/chrome/browser/chromeos/extensions/printing_metrics/printing_metrics_api_unittest.cc b/chrome/browser/chromeos/extensions/printing_metrics/printing_metrics_api_unittest.cc
index b4215ce..1ea09c3 100644
--- a/chrome/browser/chromeos/extensions/printing_metrics/printing_metrics_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/printing_metrics/printing_metrics_api_unittest.cc
@@ -147,7 +147,7 @@
               testing::Field(&api::printing_metrics::PrintJobInfo::title,
                              kTitle1),
               testing::Field(&api::printing_metrics::PrintJobInfo::status,
-                             api::printing_metrics::PRINT_JOB_STATUS_FAILED),
+                             api::printing_metrics::PrintJobStatus::kFailed),
               testing::Field(
                   &api::printing_metrics::PrintJobInfo::number_of_pages,
                   kPagesNumber)))));
diff --git a/chrome/browser/chromeos/extensions/wm/wm_desks_private_feature_ash.cc b/chrome/browser/chromeos/extensions/wm/wm_desks_private_feature_ash.cc
index 0c1c71a..38901454 100644
--- a/chrome/browser/chromeos/extensions/wm/wm_desks_private_feature_ash.cc
+++ b/chrome/browser/chromeos/extensions/wm/wm_desks_private_feature_ash.cc
@@ -42,14 +42,14 @@
     const ash::DeskTemplateType type) {
   switch (type) {
     case ash::DeskTemplateType::kTemplate:
-      return api::wm_desks_private::SavedDeskType::kKtemplate;
+      return api::wm_desks_private::SavedDeskType::kTemplate;
     case ash::DeskTemplateType::kSaveAndRecall:
-      return api::wm_desks_private::SavedDeskType::kKsaveAndRecall;
+      return api::wm_desks_private::SavedDeskType::kSaveAndRecall;
     case ash::DeskTemplateType::kFloatingWorkspace:
       // Desk API does not save/restore Floating Workspace.
-      return api::wm_desks_private::SavedDeskType::kKunknown;
+      return api::wm_desks_private::SavedDeskType::kUnknown;
     case ash::DeskTemplateType::kUnknown:
-      return api::wm_desks_private::SavedDeskType::kKunknown;
+      return api::wm_desks_private::SavedDeskType::kUnknown;
   }
 }
 
diff --git a/chrome/browser/chromeos/extensions/wm/wm_desks_private_feature_lacros.cc b/chrome/browser/chromeos/extensions/wm/wm_desks_private_feature_lacros.cc
index 3566d03..b08a0ab 100644
--- a/chrome/browser/chromeos/extensions/wm/wm_desks_private_feature_lacros.cc
+++ b/chrome/browser/chromeos/extensions/wm/wm_desks_private_feature_lacros.cc
@@ -39,11 +39,11 @@
     const crosapi::mojom::SavedDeskType type) {
   switch (type) {
     case crosapi::mojom::SavedDeskType::kTemplate:
-      return api::wm_desks_private::SavedDeskType::kKtemplate;
+      return api::wm_desks_private::SavedDeskType::kTemplate;
     case crosapi::mojom::SavedDeskType::kSaveAndRecall:
-      return api::wm_desks_private::SavedDeskType::kKsaveAndRecall;
+      return api::wm_desks_private::SavedDeskType::kSaveAndRecall;
     case crosapi::mojom::SavedDeskType::kUnknown:
-      return api::wm_desks_private::SavedDeskType::kKunknown;
+      return api::wm_desks_private::SavedDeskType::kUnknown;
   }
 }
 
diff --git a/chrome/browser/companion/core/mojom/BUILD.gn b/chrome/browser/companion/core/mojom/BUILD.gn
index 4cde2ae..aa336c5 100644
--- a/chrome/browser/companion/core/mojom/BUILD.gn
+++ b/chrome/browser/companion/core/mojom/BUILD.gn
@@ -7,7 +7,6 @@
 mojom("mojo_bindings") {
   sources = [ "companion.mojom" ]
   webui_module_path = "/"
-  use_typescript_sources = true
   public_deps = [
     "//mojo/public/mojom/base",
     "//ui/base/mojom",
diff --git a/chrome/browser/devtools/devtools_browsertest.cc b/chrome/browser/devtools/devtools_browsertest.cc
index a523ec7..ace24f6 100644
--- a/chrome/browser/devtools/devtools_browsertest.cc
+++ b/chrome/browser/devtools/devtools_browsertest.cc
@@ -487,13 +487,13 @@
   }
 
   void OpenDevToolsPopupWindow(DevToolsWindow* devtools_window) {
-    content::WindowedNotificationObserver observer(
-        content::NOTIFICATION_LOAD_STOP,
-        content::NotificationService::AllSources());
     ASSERT_TRUE(content::ExecJs(
         DevToolsWindowTesting::Get(devtools_window)->main_web_contents(),
         "window.open(\"\", \"\", \"location=0\");"));
-    observer.Wait();
+    Browser* popup_browser = BrowserList::GetInstance()->GetLastActive();
+    WebContents* popup_contents =
+        popup_browser->tab_strip_model()->GetActiveWebContents();
+    content::WaitForLoadStop(popup_contents);
   }
 
   void CloseDevToolsPopupWindow(DevToolsWindow* devtools_window) {
diff --git a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc
index 544dcdf..8d3d0ffb 100644
--- a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc
+++ b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc
@@ -104,8 +104,6 @@
       settings_dict.FindBool(kKeyBlockPasswordProtected).value_or(false);
   block_large_files_ =
       settings_dict.FindBool(kKeyBlockLargeFiles).value_or(false);
-  block_unsupported_file_types_ =
-      settings_dict.FindBool(kKeyBlockUnsupportedFileTypes).value_or(false);
   minimum_data_size_ = settings_dict.FindInt(kKeyMinimumDataSize).value_or(100);
 
   const base::Value::List* custom_messages =
@@ -199,7 +197,6 @@
   settings.default_action = default_action_;
   settings.block_password_protected_files = block_password_protected_files_;
   settings.block_large_files = block_large_files_;
-  settings.block_unsupported_file_types = block_unsupported_file_types_;
   if (is_cloud_analysis()) {
     CloudAnalysisSettings cloud_settings;
     cloud_settings.analysis_url = GURL(analysis_config_->url);
diff --git a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.h b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.h
index ef00729d..beed8d9 100644
--- a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.h
+++ b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.h
@@ -150,7 +150,6 @@
   DefaultAction default_action_ = DefaultAction::kAllow;
   bool block_password_protected_files_ = false;
   bool block_large_files_ = false;
-  bool block_unsupported_file_types_ = false;
   size_t minimum_data_size_ = 100;
   // A map from tag (dlp, malware, etc) to the custom message, "learn more" link
   // and other settings associated to a specific tag.
diff --git a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings_unittest.cc b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings_unittest.cc
index 2cd9ac1..c971bfd 100644
--- a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings_unittest.cc
+++ b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings_unittest.cc
@@ -61,7 +61,6 @@
   "default_action": "block",
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
   "minimum_data_size": 123,
 })";
 
@@ -129,7 +128,6 @@
   "default_action": "block",
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
   "minimum_data_size": 123,
 })";
 
@@ -146,7 +144,6 @@
   "default_action": "block",
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
 })";
 
 constexpr char kNormalSettingsWithCustomMessage[] = R"({
@@ -165,7 +162,6 @@
   "default_action": "block",
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
   "minimum_data_size": 123,
   "custom_messages": [
     {
@@ -197,7 +193,6 @@
   "default_action": "block",
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
   "minimum_data_size": 123,
   "require_justification_tags": ["dlp"],
 })";
@@ -290,7 +285,6 @@
   "default_action": "block",
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
   "minimum_data_size": 123,
 })";
 
@@ -441,7 +435,6 @@
   "default_action": "block",
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
   "minimum_data_size": 123,
 })";
 
@@ -495,7 +488,6 @@
   "default_action": "block",
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
 })";
 
 constexpr char kNormalSourceDestinationSettingsWithCustomMessage[] = R"({
@@ -519,7 +511,6 @@
   "default_action": "block",
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
   "minimum_data_size": 123,
   "custom_messages": [
     {
@@ -557,7 +548,6 @@
   "default_action": "block",
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
   "minimum_data_size": 123,
   "require_justification_tags": ["dlp"],
 })";
@@ -640,7 +630,6 @@
   settings.default_action = DefaultAction::kBlock;
   settings.block_password_protected_files = true;
   settings.block_large_files = true;
-  settings.block_unsupported_file_types = true;
   settings.minimum_data_size = 123;
   return settings;
 }
@@ -787,8 +776,6 @@
               expected_settings()->block_password_protected_files);
     ASSERT_EQ(analysis_settings.value().block_large_files,
               expected_settings()->block_large_files);
-    ASSERT_EQ(analysis_settings.value().block_unsupported_file_types,
-              expected_settings()->block_unsupported_file_types);
     ASSERT_TRUE(
         analysis_settings.value().cloud_or_local_settings.is_cloud_analysis());
     ASSERT_EQ(analysis_settings.value().cloud_or_local_settings.analysis_url(),
@@ -837,8 +824,6 @@
               expected_settings()->block_password_protected_files);
     ASSERT_EQ(analysis_settings.value().block_large_files,
               expected_settings()->block_large_files);
-    ASSERT_EQ(analysis_settings.value().block_unsupported_file_types,
-              expected_settings()->block_unsupported_file_types);
     ASSERT_TRUE(
         analysis_settings.value().cloud_or_local_settings.is_local_analysis());
     ASSERT_EQ(analysis_settings.value().cloud_or_local_settings.local_path(),
@@ -1031,8 +1016,6 @@
               expected_settings()->block_password_protected_files);
     ASSERT_EQ(analysis_settings.value().block_large_files,
               expected_settings()->block_large_files);
-    ASSERT_EQ(analysis_settings.value().block_unsupported_file_types,
-              expected_settings()->block_unsupported_file_types);
     ASSERT_TRUE(
         analysis_settings.value().cloud_or_local_settings.is_cloud_analysis());
     ASSERT_EQ(analysis_settings.value().cloud_or_local_settings.analysis_url(),
@@ -1081,8 +1064,6 @@
               expected_settings()->block_password_protected_files);
     ASSERT_EQ(analysis_settings.value().block_large_files,
               expected_settings()->block_large_files);
-    ASSERT_EQ(analysis_settings.value().block_unsupported_file_types,
-              expected_settings()->block_unsupported_file_types);
     ASSERT_TRUE(
         analysis_settings.value().cloud_or_local_settings.is_local_analysis());
     ASSERT_EQ(analysis_settings.value().cloud_or_local_settings.local_path(),
diff --git a/chrome/browser/enterprise/connectors/analysis/analysis_settings.h b/chrome/browser/enterprise/connectors/analysis/analysis_settings.h
index 557045f5..2100f82e 100644
--- a/chrome/browser/enterprise/connectors/analysis/analysis_settings.h
+++ b/chrome/browser/enterprise/connectors/analysis/analysis_settings.h
@@ -128,7 +128,6 @@
   DefaultAction default_action = DefaultAction::kAllow;
   bool block_password_protected_files = false;
   bool block_large_files = false;
-  bool block_unsupported_file_types = false;
 
   // Minimum text size for BulkDataEntry scans. 0 means no minimum.
   size_t minimum_data_size = 100;
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc
index 06aa192..88046caf 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc
@@ -985,7 +985,6 @@
 // - block_until_verdict
 // - block_password_protected
 // - block_large_files
-// - block_unsupported_file_types
 class ContentAnalysisDelegateBlockingSettingBrowserTest
     : public ContentAnalysisDelegateBrowserTestBase,
       public testing::WithParamInterface<std::tuple<bool, bool>> {
diff --git a/chrome/browser/enterprise/connectors/common.cc b/chrome/browser/enterprise/connectors/common.cc
index 55d2f3f..3b8debb 100644
--- a/chrome/browser/enterprise/connectors/common.cc
+++ b/chrome/browser/enterprise/connectors/common.cc
@@ -94,9 +94,6 @@
 
     case BinaryUploadService::Result::FILE_ENCRYPTED:
       return !settings.block_password_protected_files;
-
-    case BinaryUploadService::Result::DLP_SCAN_UNSUPPORTED_FILE_TYPE:
-      return !settings.block_unsupported_file_types;
   }
 }
 
@@ -445,9 +442,7 @@
 bool LocalResultIsFailure(safe_browsing::BinaryUploadService::Result result) {
   return result != safe_browsing::BinaryUploadService::Result::SUCCESS &&
          result != safe_browsing::BinaryUploadService::Result::FILE_TOO_LARGE &&
-         result != safe_browsing::BinaryUploadService::Result::FILE_ENCRYPTED &&
-         result != safe_browsing::BinaryUploadService::Result::
-                       DLP_SCAN_UNSUPPORTED_FILE_TYPE;
+         result != safe_browsing::BinaryUploadService::Result::FILE_ENCRYPTED;
 }
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/enterprise/connectors/common.h b/chrome/browser/enterprise/connectors/common.h
index c112378..86de775 100644
--- a/chrome/browser/enterprise/connectors/common.h
+++ b/chrome/browser/enterprise/connectors/common.h
@@ -52,7 +52,6 @@
 constexpr char kKeyBlockUntilVerdict[] = "block_until_verdict";
 constexpr char kKeyBlockPasswordProtected[] = "block_password_protected";
 constexpr char kKeyBlockLargeFiles[] = "block_large_files";
-constexpr char kKeyBlockUnsupportedFileTypes[] = "block_unsupported_file_types";
 constexpr char kKeyMinimumDataSize[] = "minimum_data_size";
 constexpr char kKeyEnabledEventNames[] = "enabled_event_names";
 constexpr char kKeyCustomMessages[] = "custom_messages";
diff --git a/chrome/browser/enterprise/connectors/common_unittest.cc b/chrome/browser/enterprise/connectors/common_unittest.cc
index e1e17b1e..46e17f24a 100644
--- a/chrome/browser/enterprise/connectors/common_unittest.cc
+++ b/chrome/browser/enterprise/connectors/common_unittest.cc
@@ -108,22 +108,6 @@
                 safe_browsing::BinaryUploadService::Result::FILE_ENCRYPTED));
 }
 
-TEST_P(EnterpriseConnectorsResultShouldAllowDataUseTest,
-       BlockUnsupportedFileTypes) {
-  auto pref = base::StringPrintf(R"(
-    {
-      "service_provider": "google",
-      "enable": [{"url_list": ["*"], "tags": ["dlp"]}],
-      "block_unsupported_file_types": %s
-    })",
-                                 bool_setting());
-  test::SetAnalysisConnector(profile()->GetPrefs(), FILE_ATTACHED, pref);
-  EXPECT_EQ(allowed(),
-            ResultShouldAllowDataUse(
-                settings(), safe_browsing::BinaryUploadService::Result::
-                                DLP_SCAN_UNSUPPORTED_FILE_TYPE));
-}
-
 TEST_P(EnterpriseConnectorsResultShouldAllowDataUseTest, BlockUploadFailure) {
   auto pref = base::StringPrintf(R"(
     {
diff --git a/chrome/browser/enterprise/connectors/connectors_manager_unittest.cc b/chrome/browser/enterprise/connectors/connectors_manager_unittest.cc
index e545d72..c06464c 100644
--- a/chrome/browser/enterprise/connectors/connectors_manager_unittest.cc
+++ b/chrome/browser/enterprise/connectors/connectors_manager_unittest.cc
@@ -67,7 +67,6 @@
     "block_until_verdict": 1,
     "block_password_protected": true,
     "block_large_files": true,
-    "block_unsupported_file_types": true,
   },
 ])";
 
@@ -83,7 +82,6 @@
     "block_until_verdict": 1,
     "block_password_protected": true,
     "block_large_files": true,
-    "block_unsupported_file_types": true,
   },
 ])";
 
@@ -115,8 +113,6 @@
     ASSERT_EQ(settings.block_password_protected_files,
               expected_block_password_protected_files_);
     ASSERT_EQ(settings.block_large_files, expected_block_large_files_);
-    ASSERT_EQ(settings.block_unsupported_file_types,
-              expected_block_unsupported_file_types_);
     for (const auto& expected_tag : expected_tags_) {
       const std::string& tag = expected_tag.first;
       ASSERT_TRUE(settings.tags.count(tag));
@@ -178,7 +174,6 @@
   BlockUntilVerdict expected_block_until_verdict_ = BlockUntilVerdict::kNoBlock;
   bool expected_block_password_protected_files_ = false;
   bool expected_block_large_files_ = false;
-  bool expected_block_unsupported_file_types_ = false;
 
   std::set<std::string> expected_mime_types_;
 };
@@ -246,8 +241,6 @@
           expected_settings.value().block_until_verdict;
       expected_block_password_protected_files_ =
           expected_settings.value().block_password_protected_files;
-      expected_block_unsupported_file_types_ =
-          expected_settings.value().block_unsupported_file_types;
       expected_block_large_files_ = expected_settings.value().block_large_files;
     }
   }
@@ -263,7 +256,6 @@
     settings.block_until_verdict = BlockUntilVerdict::kBlock;
     settings.block_password_protected_files = true;
     settings.block_large_files = true;
-    settings.block_unsupported_file_types = true;
 
     if (url == kDlpAndMalwareUrl)
       settings.tags = {{"dlp", TagSettings()}, {"malware", TagSettings()}};
@@ -411,7 +403,6 @@
   "block_until_verdict": 1,
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
   "minimum_data_size": 123,
 }])";
 
@@ -479,7 +470,6 @@
   "block_until_verdict": 1,
   "block_password_protected": true,
   "block_large_files": true,
-  "block_unsupported_file_types": true,
   "minimum_data_size": 123,
 }])";
 
@@ -579,8 +569,6 @@
           expected_settings.value().block_until_verdict;
       expected_block_password_protected_files_ =
           expected_settings.value().block_password_protected_files;
-      expected_block_unsupported_file_types_ =
-          expected_settings.value().block_unsupported_file_types;
       expected_block_large_files_ = expected_settings.value().block_large_files;
     }
   }
@@ -599,7 +587,6 @@
     settings.block_until_verdict = BlockUntilVerdict::kBlock;
     settings.block_password_protected_files = true;
     settings.block_large_files = true;
-    settings.block_unsupported_file_types = true;
 
     if (volume_pair == &kDlpMalwareVolumePair1 ||
         volume_pair == &kDlpMalwareVolumePair2) {
@@ -736,7 +723,6 @@
     expected_block_until_verdict_ = BlockUntilVerdict::kBlock;
     expected_block_password_protected_files_ = true;
     expected_block_large_files_ = true;
-    expected_block_unsupported_file_types_ = true;
 
     // The "local_test" service provider doesn't support the "malware" tag, so
     // remove it from expectations.
@@ -850,7 +836,6 @@
     expected_block_until_verdict_ = BlockUntilVerdict::kBlock;
     expected_block_password_protected_files_ = true;
     expected_block_large_files_ = true;
-    expected_block_unsupported_file_types_ = true;
 
     // The "local_test" service provider doesn't support the "malware" tag, so
     // remove it from expectations.
@@ -965,7 +950,6 @@
     expected_block_until_verdict_ = BlockUntilVerdict::kBlock;
     expected_block_password_protected_files_ = true;
     expected_block_large_files_ = true;
-    expected_block_unsupported_file_types_ = true;
 
     // The "local_test" service provider doesn't support the "malware" tag, so
     // remove it from expectations.
@@ -992,7 +976,6 @@
     expected_block_until_verdict_ = BlockUntilVerdict::kBlock;
     expected_block_password_protected_files_ = true;
     expected_block_large_files_ = true;
-    expected_block_unsupported_file_types_ = true;
 
     expected_tags_ = {{"dlp", TagSettings()}, {"malware", TagSettings()}};
 
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
index 93301e4..659636d2d 100644
--- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
+++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
@@ -942,4 +942,30 @@
   return RespondNow(Error(kErrorDeviceAuthUnavailable));
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// AutofillPrivateBulkDeleteAllCvcsFunction
+
+ExtensionFunction::ResponseAction
+AutofillPrivateBulkDeleteAllCvcsFunction::Run() {
+  autofill::ContentAutofillClient* client =
+      autofill::ContentAutofillClient::FromWebContents(GetSenderWebContents());
+  if (!client) {
+    return RespondNow(Error(kErrorDataUnavailable));
+  }
+
+  autofill::PersonalDataManager* personal_data =
+      client->GetPersonalDataManager();
+  if (!personal_data || !personal_data->IsDataLoaded()) {
+    return RespondNow(Error(kErrorDataUnavailable));
+  }
+
+  // Clear local and server CVCs from the webdata database. For server CVCs,
+  // this will also clear them from the Chrome sync server and thus other
+  // devices.
+  personal_data->ClearLocalCvcs();
+  personal_data->ClearServerCvcs();
+
+  return RespondNow(NoArguments());
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.h b/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
index 215229ed..2bdf16f 100644
--- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
+++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
@@ -368,6 +368,23 @@
   ResponseAction Run() override;
 };
 
+class AutofillPrivateBulkDeleteAllCvcsFunction : public ExtensionFunction {
+ public:
+  AutofillPrivateBulkDeleteAllCvcsFunction() = default;
+  AutofillPrivateBulkDeleteAllCvcsFunction(
+      const AutofillPrivateBulkDeleteAllCvcsFunction&) = delete;
+  AutofillPrivateBulkDeleteAllCvcsFunction& operator=(
+      const AutofillPrivateBulkDeleteAllCvcsFunction&) = delete;
+  DECLARE_EXTENSION_FUNCTION("autofillPrivate.bulkDeleteAllCvcs",
+                             AUTOFILLPRIVATE_BULKDELETEALLCVCS)
+
+ protected:
+  ~AutofillPrivateBulkDeleteAllCvcsFunction() override = default;
+
+  // ExtensionFunction overrides.
+  ResponseAction Run() override;
+};
+
 }  // namespace extensions
 
 #endif  // CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_PRIVATE_AUTOFILL_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api_unittest.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_api_unittest.cc
index 5223f9b5..320127f 100644
--- a/chrome/browser/extensions/api/autofill_private/autofill_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/extensions/api/autofill_private/autofill_private_api.h"
 
+#include <string>
 #include <vector>
 
 #include "chrome/browser/autofill/autofill_uitest_util.h"
@@ -13,6 +14,8 @@
 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
 #include "components/autofill/content/browser/test_autofill_client_injector.h"
 #include "components/autofill/content/browser/test_content_autofill_client.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/metrics/payments/mandatory_reauth_metrics.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/device_reauth/mock_device_authenticator.h"
@@ -160,3 +163,80 @@
                          MandatoryReauthSettingsPageMetricsTest,
                          testing::Combine(testing::Bool(), testing::Bool()));
 #endif  // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
+
+class AutofillPrivateApiUnitTest : public extensions::ExtensionApiTest {
+ public:
+  AutofillPrivateApiUnitTest() = default;
+  AutofillPrivateApiUnitTest(const AutofillPrivateApiUnitTest&) = delete;
+  AutofillPrivateApiUnitTest& operator=(const AutofillPrivateApiUnitTest&) =
+      delete;
+  ~AutofillPrivateApiUnitTest() override = default;
+
+  void SetUpOnMainThread() override {
+    ExtensionApiTest::SetUpOnMainThread();
+    autofill_client()->GetPersonalDataManager()->SetSyncingForTest(
+        /*is_syncing_for_test=*/true);
+  }
+
+  autofill::TestContentAutofillClient* autofill_client() {
+    return test_autofill_client_injector_
+        [browser()->tab_strip_model()->GetActiveWebContents()];
+  }
+
+ protected:
+  bool RunAutofillSubtest(const std::string& subtest) {
+    autofill::WaitForPersonalDataManagerToBeLoaded(profile());
+
+    const std::string extension_url = "main.html?" + subtest;
+    return RunExtensionTest("autofill_private",
+                            {.extension_url = extension_url.c_str()},
+                            {.load_as_component = true});
+  }
+
+ private:
+  autofill::TestAutofillClientInjector<autofill::TestContentAutofillClient>
+      test_autofill_client_injector_;
+};
+
+// Test to verify all the CVCs(server and local) are bulk deleted when the API
+// is called.
+IN_PROC_BROWSER_TEST_F(AutofillPrivateApiUnitTest, BulkDeleteAllCvcs) {
+  autofill::CreditCard local_card =
+      autofill::test::WithCvc(autofill::test::GetCreditCard(), u"789");
+  autofill::CreditCard server_card =
+      autofill::test::WithCvc(autofill::test::GetMaskedServerCard(), u"098");
+  autofill::TestPersonalDataManager* personal_data =
+      autofill_client()->GetPersonalDataManager();
+  personal_data->AddCreditCard(local_card);
+  personal_data->AddServerCreditCard(server_card);
+
+  // Verify that cards are same as above and the CVCs are present for both of
+  // them.
+  ASSERT_EQ(personal_data->GetCreditCards().size(), 2u);
+  for (const autofill::CreditCard* card : personal_data->GetCreditCards()) {
+    EXPECT_FALSE(card->cvc().empty());
+    if (card->record_type() ==
+        autofill::CreditCard::RecordType::kMaskedServerCard) {
+      EXPECT_EQ(card->number(), server_card.number());
+      EXPECT_EQ(card->cvc(), server_card.cvc());
+    } else {
+      EXPECT_EQ(card->number(), local_card.number());
+      EXPECT_EQ(card->cvc(), local_card.cvc());
+    }
+  }
+
+  RunAutofillSubtest("bulkDeleteAllCvcs");
+
+  // Verify that cards are same as above and the CVCs are deleted for both of
+  // them.
+  ASSERT_EQ(personal_data->GetCreditCards().size(), 2u);
+  for (const autofill::CreditCard* card : personal_data->GetCreditCards()) {
+    EXPECT_TRUE(card->cvc().empty());
+    if (card->record_type() ==
+        autofill::CreditCard::RecordType::kMaskedServerCard) {
+      EXPECT_EQ(card->number(), server_card.number());
+    } else {
+      EXPECT_EQ(card->number(), local_card.number());
+    }
+  }
+}
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc
index 2c225401..2e39217 100644
--- a/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc
+++ b/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc
@@ -245,4 +245,8 @@
                    "PaymentsUserAuthSuccessfulToShowEditLocalCardDialog"));
 }
 
+IN_PROC_BROWSER_TEST_F(AutofillPrivateApiTest, bulkDeleteAllCvcs) {
+  EXPECT_TRUE(RunAutofillSubtest("bulkDeleteAllCvcs")) << message_;
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_condition_tracker_test.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_condition_tracker_test.cc
index 4a0993fb..1f8b451 100644
--- a/chrome/browser/extensions/api/declarative_content/declarative_content_condition_tracker_test.cc
+++ b/chrome/browser/extensions/api/declarative_content/declarative_content_condition_tracker_test.cc
@@ -47,9 +47,7 @@
 
 TestingProfile* DeclarativeContentConditionTrackerTest::profile() {
   if (!profile_) {
-    for (auto& pair : GetTestingFactories())
-      profile_builder_.AddTestingFactory(pair.first, pair.second);
-
+    profile_builder_.AddTestingFactories(GetTestingFactories());
     profile_ = profile_builder_.Build();
   }
   return profile_.get();
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
index 9a928f9..45eed07 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -545,34 +545,6 @@
         extensions::events::INPUT_IME_ON_SURROUNDING_TEXT_CHANGED,
         input_ime::OnSurroundingTextChanged::kEventName, std::move(args));
   }
-  void OnTouch(ui::EventPointerType pointerType) override {
-    if (extension_id_.empty() ||
-        !HasListener(input_method_private::OnTouch::kEventName))
-      return;
-
-    std::string pointer = "";
-    switch (pointerType) {
-      case ui::EventPointerType::kPen:
-        pointer = "pen";
-        break;
-      case ui::EventPointerType::kMouse:
-        pointer = "mouse";
-        break;
-      case ui::EventPointerType::kTouch:
-        pointer = "touch";
-        break;
-      default:
-        pointer = "other";
-        break;
-    }
-
-    auto args(input_method_private::OnTouch::Create(
-        input_method_private::ParseFocusReason(pointer)));
-
-    DispatchEventToExtension(extensions::events::INPUT_METHOD_PRIVATE_ON_TOUCH,
-                             input_method_private::OnTouch::kEventName,
-                             std::move(args));
-  }
 
   void OnAssistiveWindowButtonClicked(
       const ui::ime::AssistiveWindowButton& button) override {
diff --git a/chrome/browser/extensions/api/processes/processes_api.cc b/chrome/browser/extensions/api/processes/processes_api.cc
index 950cb065..83bd66e 100644
--- a/chrome/browser/extensions/api/processes/processes_api.cc
+++ b/chrome/browser/extensions/api/processes/processes_api.cc
@@ -75,35 +75,35 @@
     task_manager::Task::Type task_type) {
   switch (task_type) {
     case task_manager::Task::BROWSER:
-      return api::processes::PROCESS_TYPE_BROWSER;
+      return api::processes::ProcessType::kBrowser;
 
     case task_manager::Task::RENDERER:
-      return api::processes::PROCESS_TYPE_RENDERER;
+      return api::processes::ProcessType::kRenderer;
 
     case task_manager::Task::EXTENSION:
     case task_manager::Task::GUEST:
-      return api::processes::PROCESS_TYPE_EXTENSION;
+      return api::processes::ProcessType::kExtension;
 
     case task_manager::Task::PLUGIN:
-      return api::processes::PROCESS_TYPE_PLUGIN;
+      return api::processes::ProcessType::kPlugin;
 
     case task_manager::Task::NACL:
-      return api::processes::PROCESS_TYPE_NACL;
+      return api::processes::ProcessType::kNacl;
 
     // TODO(https://crbug.com/1048715): Assign a different process type for each
     //                                  worker type.
     case task_manager::Task::DEDICATED_WORKER:
     case task_manager::Task::SHARED_WORKER:
-      return api::processes::PROCESS_TYPE_WORKER;
+      return api::processes::ProcessType::kWorker;
 
     case task_manager::Task::SERVICE_WORKER:
-      return api::processes::PROCESS_TYPE_SERVICE_WORKER;
+      return api::processes::ProcessType::kServiceWorker;
 
     case task_manager::Task::UTILITY:
-      return api::processes::PROCESS_TYPE_UTILITY;
+      return api::processes::ProcessType::kUtility;
 
     case task_manager::Task::GPU:
-      return api::processes::PROCESS_TYPE_GPU;
+      return api::processes::ProcessType::kGpu;
 
     case task_manager::Task::UNKNOWN:
     case task_manager::Task::ARC:
@@ -114,11 +114,11 @@
     // TODO(crbug.com/1186464): Do not expose lacros tasks for now. Defer
     // the decision until further discussion is made.
     case task_manager::Task::LACROS:
-      return api::processes::PROCESS_TYPE_OTHER;
+      return api::processes::ProcessType::kOther;
   }
 
   NOTREACHED() << "Unknown task type.";
-  return api::processes::PROCESS_TYPE_NONE;
+  return api::processes::ProcessType::kNone;
 }
 
 // Fills |out_process| with the data of the process in which the task with |id|
diff --git a/chrome/browser/extensions/extension_service_test_base.cc b/chrome/browser/extensions/extension_service_test_base.cc
index 9a15abc8..5726072 100644
--- a/chrome/browser/extensions/extension_service_test_base.cc
+++ b/chrome/browser/extensions/extension_service_test_base.cc
@@ -311,9 +311,9 @@
     const std::string& extension_id,
     const std::string& pref_path,
     bool expected_val) {
-  std::string msg = base::StringPrintf("while checking: %s %s == %s",
-                                       extension_id.c_str(), pref_path.c_str(),
-                                       expected_val ? "true" : "false");
+  std::string msg =
+      base::StringPrintf("while checking: %s %s == %s", extension_id.c_str(),
+                         pref_path.c_str(), expected_val ? "true" : "false");
 
   PrefService* prefs = profile()->GetPrefs();
   const base::Value::Dict& dict = prefs->GetDict(pref_names::kExtensions);
@@ -321,13 +321,13 @@
   const base::Value::Dict* pref = dict.FindDict(extension_id);
   if (!pref) {
     return testing::AssertionFailure()
-        << "extension pref does not exist " << msg;
+           << "extension pref does not exist " << msg;
   }
 
   absl::optional<bool> val = pref->FindBoolByDottedPath(pref_path);
   if (!val.has_value()) {
     return testing::AssertionFailure()
-        << pref_path << " pref not found " << msg;
+           << pref_path << " pref not found " << msg;
   }
 
   return expected_val == val.value() ? testing::AssertionSuccess()
@@ -382,7 +382,11 @@
       base::CommandLine::ForCurrentProcess());
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  kiosk_app_manager_ = std::make_unique<ash::KioskAppManager>();
+  // TODO(b/308107135) own KioskController instead of KioskAppManager.
+  // A test might have initialized a `KioskAppManager` already.
+  if (!ash::KioskAppManager::IsInitialized()) {
+    kiosk_app_manager_ = std::make_unique<ash::KioskAppManager>();
+  }
 #endif
 }
 
@@ -392,8 +396,9 @@
         content::StoragePartitionConfig::CreateDefault(profile());
     auto* partition = profile_->GetStoragePartition(
         default_storage_partition_config, /*can_create=*/false);
-    if (partition)
+    if (partition) {
       partition->WaitForDeletionTasksForTesting();
+    }
   }
   policy_provider_.Shutdown();
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -416,8 +421,9 @@
 // TODO(crbug.com/1414225): Refactor this convenience upstream to test callers.
 // Possibly just BuiltInAppTest.BuildGuestMode.
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  if (profile_->IsGuestSession())
+  if (profile_->IsGuestSession()) {
     return profile_->GetPrimaryOTRProfile(/*create_if_needed=*/true);
+  }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   return profile_.get();
@@ -432,8 +438,9 @@
     const ExtensionServiceInitParams& params) {
   TestExtensionSystem* system =
       static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()));
-  if (!params.is_first_run)
+  if (!params.is_first_run) {
     ExtensionPrefs::Get(profile())->SetAlertSystemFirstRun();
+  }
 
   service_ = system->CreateExtensionService(
       base::CommandLine::ForCurrentProcess(), extensions_install_dir_,
@@ -453,8 +460,9 @@
                                 service_->shared_module_service());
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  if (!params.enable_install_limiter)
+  if (!params.enable_install_limiter) {
     InstallLimiter::Get(profile())->DisableForTest();
+  }
 #endif
 }
 
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc
index b6c139e..190f0a46 100644
--- a/chrome/browser/extensions/tab_helper.cc
+++ b/chrome/browser/extensions/tab_helper.cc
@@ -404,9 +404,13 @@
   if (render_frame_host->IsRenderFrameLive()) {
     SessionID id = sessions::SessionTabHelper::IdForTab(web_contents());
     CHECK(id.is_valid());
-    ExtensionWebContentsObserver::GetForWebContents(web_contents())
-        ->GetLocalFrame(render_frame_host)
-        ->SetTabId(id.id());
+    auto* local_frame =
+        ExtensionWebContentsObserver::GetForWebContents(web_contents())
+            ->GetLocalFrame(render_frame_host);
+    if (!local_frame) {
+      return;
+    }
+    local_frame->SetTabId(id.id());
   }
 }
 
diff --git a/chrome/browser/first_party_sets/first_party_sets_policy_browsertest.cc b/chrome/browser/first_party_sets/first_party_sets_policy_browsertest.cc
index 8317b7a7..7d93b0b 100644
--- a/chrome/browser/first_party_sets/first_party_sets_policy_browsertest.cc
+++ b/chrome/browser/first_party_sets/first_party_sets_policy_browsertest.cc
@@ -17,6 +17,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
+#include "components/content_settings/core/common/features.h"
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/permissions/test/mock_permission_prompt_factory.h"
 #include "components/policy/core/common/policy_map.h"
@@ -56,7 +57,8 @@
       : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
     std::vector<base::test::FeatureRef> enabled_features = {
         blink::features::kStorageAccessAPI};
-    std::vector<base::test::FeatureRef> disabled_features;
+    std::vector<base::test::FeatureRef> disabled_features = {
+        content_settings::features::kTrackingProtection3pcd};
     if (IsFeatureEnabled()) {
       enabled_features.emplace_back(features::kFirstPartySets);
     } else {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index c15b073..905ba5c 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -3809,11 +3809,6 @@
     "expiry_milestone": 130
   },
   {
-    "name": "enable-windows-gaming-input-data-fetcher",
-    "owners": ["gabrielbrito@microsoft.com", "qiaye@microsoft.com" ],
-    "expiry_milestone": 121
-  },
-  {
     "name": "enable-winrt-geolocation-implementation",
     "owners": [ "pelavall@microsoft.com", "deviceapi-team@google.com" ],
     "expiry_milestone": 125
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 7fcd305..5479c22 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1266,12 +1266,6 @@
 const char kEnableWebUsbOnExtensionServiceWorkerDescription[] =
     "When enabled, WebUSB API is available on extension service workers.";
 
-const char kEnableWindowsGamingInputDataFetcherName[] =
-    "Enable Windows.Gaming.Input";
-const char kEnableWindowsGamingInputDataFetcherDescription[] =
-    "Enable Windows.Gaming.Input by default to provide game controller "
-    "support on Windows 10 desktop.";
-
 const char kBlockInsecurePrivateNetworkRequestsName[] =
     "Block insecure private network requests.";
 const char kBlockInsecurePrivateNetworkRequestsDescription[] =
@@ -1625,11 +1619,6 @@
 const char kFedCmIdPRegistrationDescription[] =
     "Enables RPs to get identity credentials from registered IdPs.";
 
-const char kFedCmLogoutRpsName[] = "FedCM with logoutRPs";
-const char kFedCmLogoutRpsDescription[] =
-    "Enables an IDP to declare itself logged out and request front-channel "
-    "logout.";
-
 const char kFedCmMetricsEndpointName[] = "FedCmMetricsEndpoint";
 const char kFedCmMetricsEndpointDescription[] =
     "Allows the FedCM API to send performance measurement to the metrics "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 546b2bf..299e86b 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -658,9 +658,6 @@
 extern const char kEnableWebUsbOnExtensionServiceWorkerName[];
 extern const char kEnableWebUsbOnExtensionServiceWorkerDescription[];
 
-extern const char kEnableWindowsGamingInputDataFetcherName[];
-extern const char kEnableWindowsGamingInputDataFetcherDescription[];
-
 extern const char kBlockInsecurePrivateNetworkRequestsName[];
 extern const char kBlockInsecurePrivateNetworkRequestsDescription[];
 
@@ -929,9 +926,6 @@
 extern const char kFedCmMetricsEndpointName[];
 extern const char kFedCmMetricsEndpointDescription[];
 
-extern const char kFedCmLogoutRpsName[];
-extern const char kFedCmLogoutRpsDescription[];
-
 extern const char kFedCmMultiIdpName[];
 extern const char kFedCmMultiIdpDescription[];
 
diff --git a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/PaneListBuilder.java b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/PaneListBuilder.java
index 6ea9fad..2d2724e 100644
--- a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/PaneListBuilder.java
+++ b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/PaneListBuilder.java
@@ -10,7 +10,7 @@
 import com.google.common.collect.ImmutableMap;
 
 import org.chromium.base.Log;
-import org.chromium.base.supplier.Supplier;
+import org.chromium.base.supplier.LazyOneshotSupplier;
 
 import java.util.HashMap;
 import java.util.Locale;
@@ -25,7 +25,7 @@
      * All {@link PaneId}s and {@link Pane}s that were registered before {@link #build()} is
      * invoked.
      */
-    private @Nullable HashMap<Integer, Supplier<Pane>> mRegisteredPanes =
+    private @Nullable HashMap<Integer, LazyOneshotSupplier<Pane>> mRegisteredPanes =
             new HashMap<>(PaneId.COUNT);
 
     /**
@@ -38,11 +38,14 @@
 
     /**
      * Register a new Pane for the Hub. This operation is invalid if {@link #build()} was invoked.
+     *
      * @param paneId The {@link PaneId} to use for {@code pane}.
      * @param paneSupplier A supplier for a {@link Pane}. It is recommended that the underlying
-     *                     {@link Pane} is lazily initialized.
+     *     {@link Pane} is lazily initialized. {@link LazyOneshotSupplier#get()} will not be called
+     *     at registration time to facilitate lazy initialization.
      */
-    public PaneListBuilder registerPane(@PaneId int paneId, @NonNull Supplier<Pane> paneSupplier) {
+    public PaneListBuilder registerPane(
+            @PaneId int paneId, @NonNull LazyOneshotSupplier<Pane> paneSupplier) {
         if (isBuilt()) {
             throw new IllegalStateException(
                     "PaneListBuilder#build() was already invoked. Cannot add a pane for " + paneId);
@@ -68,14 +71,15 @@
      * Builds a {@link ImmutableMap} of Panes keyed by {@link PaneId} and ordered according to the
      * supplied {@link PaneOrderController}.
      */
-    ImmutableMap<Integer, Supplier<Pane>> build() {
+    ImmutableMap<Integer, LazyOneshotSupplier<Pane>> build() {
         if (isBuilt()) {
             throw new IllegalStateException("PaneListBuilder#build() was already invoked");
         }
 
-        ImmutableMap.Builder<Integer, Supplier<Pane>> panesBuilder = ImmutableMap.builder();
+        ImmutableMap.Builder<Integer, LazyOneshotSupplier<Pane>> panesBuilder =
+                ImmutableMap.builder();
         for (@PaneId int paneId : mPaneOrderController.getPaneOrder()) {
-            Supplier<Pane> paneSupplier = mRegisteredPanes.get(paneId);
+            LazyOneshotSupplier<Pane> paneSupplier = mRegisteredPanes.get(paneId);
             if (paneSupplier == null) {
                 Log.d(TAG, "No Pane was registered for " + paneId);
                 continue;
diff --git a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/PaneListBuilderUnitTest.java b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/PaneListBuilderUnitTest.java
index 13101e7..41382a8 100644
--- a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/PaneListBuilderUnitTest.java
+++ b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/PaneListBuilderUnitTest.java
@@ -8,29 +8,28 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Mockito.verifyNoInteractions;
 
 import androidx.test.filters.SmallTest;
 
 import com.google.common.collect.ImmutableSet;
 
-import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
-import org.chromium.base.supplier.Supplier;
+import org.chromium.base.supplier.LazyOneshotSupplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 
 /** Unit tests for {@link PaneListBuilder}. */
 @RunWith(BaseRobolectricTestRunner.class)
 public class PaneListBuilderUnitTest {
-    @Mock private Supplier<Pane> mMockSupplier;
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
 
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
+    @Mock private LazyOneshotSupplier<Pane> mMockSupplier;
 
     @Test
     @SmallTest
@@ -54,6 +53,7 @@
 
         assertEquals(3, panes.size());
         assertEquals(orderController.getPaneOrder(), panes.keySet());
+        verifyNoInteractions(mMockSupplier);
     }
 
     @Test
@@ -70,6 +70,7 @@
 
         assertEquals(3, panes.size());
         assertEquals(orderController.getPaneOrder().asList(), panes.keySet().asList());
+        verifyNoInteractions(mMockSupplier);
     }
 
     @Test
@@ -85,23 +86,20 @@
         assertEquals(1, panes.size());
         assertTrue(panes.containsKey(PaneId.TAB_SWITCHER));
         assertFalse(panes.containsKey(PaneId.BOOKMARKS));
+        verifyNoInteractions(mMockSupplier);
     }
 
     @Test
     @SmallTest
     public void testAlreadyBuiltThrowsException() {
         PaneOrderController orderController = new DefaultPaneOrderController();
-
         PaneListBuilder builder = new PaneListBuilder(orderController);
-
         assertFalse(builder.isBuilt());
 
         builder.registerPane(PaneId.TAB_SWITCHER, mMockSupplier);
-
         assertFalse(builder.isBuilt());
 
         builder.build();
-
         assertTrue(builder.isBuilt());
 
         try {
@@ -117,15 +115,12 @@
         } catch (IllegalStateException e) {
             // This should catch the exception silently.
         }
+        verifyNoInteractions(mMockSupplier);
     }
 
     private PaneOrderController createReverseDefaultOrderController() {
-        return new PaneOrderController() {
-            @Override
-            public ImmutableSet<Integer> getPaneOrder() {
-                return ImmutableSet.copyOf(
+        return () ->
+                ImmutableSet.copyOf(
                         new DefaultPaneOrderController().getPaneOrder().asList().reverse());
-            }
-        };
     }
 }
diff --git a/chrome/browser/hub/internal/BUILD.gn b/chrome/browser/hub/internal/BUILD.gn
index 12422c25..1c462c1b 100644
--- a/chrome/browser/hub/internal/BUILD.gn
+++ b/chrome/browser/hub/internal/BUILD.gn
@@ -9,6 +9,9 @@
   visibility = [
     ":*",
     "//chrome/android:*",
+
+    # For access to resource IDs and view names for Hub public transit framework code.
+    "//chrome/test/android:chrome_java_transit",
   ]
   sources = [
     "android/java/src/org/chromium/chrome/browser/hub/DelegateButtonData.java",
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubCoordinatorUnitTest.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubCoordinatorUnitTest.java
index 2695563..670098c 100644
--- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubCoordinatorUnitTest.java
+++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubCoordinatorUnitTest.java
@@ -24,6 +24,7 @@
 import org.mockito.junit.MockitoRule;
 import org.robolectric.shadows.ShadowLooper;
 
+import org.chromium.base.supplier.LazyOneshotSupplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.components.browser_ui.widget.gesture.BackPressHandler.BackPressResult;
 import org.chromium.ui.base.TestActivity;
@@ -50,13 +51,15 @@
 
         PaneListBuilder builder =
                 new PaneListBuilder(new DefaultPaneOrderController())
-                        .registerPane(PaneId.TAB_SWITCHER, () -> mTabSwitcherPane)
                         .registerPane(
-                                PaneId.INCOGNITO_TAB_SWITCHER, () -> mIncognitoTabSwitcherPane);
+                                PaneId.TAB_SWITCHER,
+                                LazyOneshotSupplier.fromValue(mTabSwitcherPane))
+                        .registerPane(
+                                PaneId.INCOGNITO_TAB_SWITCHER,
+                                LazyOneshotSupplier.fromValue(mIncognitoTabSwitcherPane));
         mPaneManager = new PaneManagerImpl(builder);
         assertTrue(mPaneManager.focusPane(PaneId.TAB_SWITCHER));
         assertEquals(mTabSwitcherPane, mPaneManager.getFocusedPaneSupplier().get());
-
         mActivityScenarioRule.getScenario().onActivity(this::onActivity);
     }
 
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImplUnitTest.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImplUnitTest.java
index a1c9551..866ee58 100644
--- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImplUnitTest.java
+++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImplUnitTest.java
@@ -24,6 +24,7 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import org.chromium.base.supplier.LazyOneshotSupplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.ui.base.TestActivity;
 
@@ -58,7 +59,9 @@
     public void testCreatesPaneManager() {
         PaneListBuilder builder =
                 new PaneListBuilder(new DefaultPaneOrderController())
-                        .registerPane(PaneId.TAB_SWITCHER, () -> mTabSwitcherPane);
+                        .registerPane(
+                                PaneId.TAB_SWITCHER,
+                                LazyOneshotSupplier.fromValue(mTabSwitcherPane));
         HubManager hubManager = HubManagerFactory.createHubManager(mActivity, builder);
 
         PaneManager paneManager = hubManager.getPaneManager();
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarCoordinator.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarCoordinator.java
index 46a8df8..a652e6f 100644
--- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarCoordinator.java
+++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarCoordinator.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.hub;
 
-
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
 
@@ -12,7 +11,11 @@
 public class HubToolbarCoordinator {
     private final HubToolbarMediator mMediator;
 
-    /** Eagerly creates the component, but will not be rooted in the view tree yet. */
+    /**
+     * Eagerly creates the component, but will not be rooted in the view tree yet.
+     *
+     * @param hubToolbarView The root view of this component. Inserted into hierarchy for us.
+     */
     public HubToolbarCoordinator(HubToolbarView hubToolbarView) {
         PropertyModel model = new PropertyModel.Builder(HubToolbarProperties.ALL_KEYS).build();
         PropertyModelChangeProcessor.create(model, hubToolbarView, HubToolbarViewBinder::bind);
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneBackStackHandlerUnitTest.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneBackStackHandlerUnitTest.java
index 605e1f39..32e1aae 100644
--- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneBackStackHandlerUnitTest.java
+++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneBackStackHandlerUnitTest.java
@@ -22,6 +22,7 @@
 import org.mockito.junit.MockitoRule;
 import org.robolectric.shadows.ShadowLooper;
 
+import org.chromium.base.supplier.LazyOneshotSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.components.browser_ui.widget.gesture.BackPressHandler.BackPressResult;
@@ -51,10 +52,14 @@
 
         PaneListBuilder builder =
                 new PaneListBuilder(new DefaultPaneOrderController())
-                        .registerPane(PaneId.TAB_SWITCHER, () -> mTabSwitcherPane)
                         .registerPane(
-                                PaneId.INCOGNITO_TAB_SWITCHER, () -> mIncognitoTabSwitcherPane)
-                        .registerPane(PaneId.BOOKMARKS, () -> mBookmarksPane);
+                                PaneId.TAB_SWITCHER,
+                                LazyOneshotSupplier.fromValue(mTabSwitcherPane))
+                        .registerPane(
+                                PaneId.INCOGNITO_TAB_SWITCHER,
+                                LazyOneshotSupplier.fromValue(mIncognitoTabSwitcherPane))
+                        .registerPane(
+                                PaneId.BOOKMARKS, LazyOneshotSupplier.fromValue(mBookmarksPane));
 
         mPaneManager = new PaneManagerImpl(builder);
         mBackStackHandler = new PaneBackStackHandler(mPaneManager);
@@ -214,7 +219,7 @@
 
     @Test
     @SmallTest
-    public void testCompleltyFailToFocus() {
+    public void testCompletelyFailToFocus() {
         mBackStackHandler = new PaneBackStackHandler(mMockPaneManager);
         ShadowLooper.runUiThreadTasks();
         assertFalse(mBackStackHandler.getHandleBackPressChangedSupplier().get());
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneManagerImpl.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneManagerImpl.java
index 00a8822..f070489 100644
--- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneManagerImpl.java
+++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneManagerImpl.java
@@ -8,15 +8,15 @@
 
 import com.google.common.collect.ImmutableMap;
 
+import org.chromium.base.supplier.LazyOneshotSupplier;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
-import org.chromium.base.supplier.Supplier;
 
 /**
  * Implementation of {@link PaneManager} for managing {@link Pane}s.
  */
 public class PaneManagerImpl implements PaneManager {
-    private final ImmutableMap<Integer, Supplier<Pane>> mPanes;
+    private final ImmutableMap<Integer, LazyOneshotSupplier<Pane>> mPanes;
 
     private final ObservableSupplierImpl<Pane> mCurrentPaneSupplierImpl =
             new ObservableSupplierImpl<>();
@@ -39,7 +39,7 @@
     public boolean focusPane(@PaneId int paneId) {
         // TODO(crbug/1482286): This is an incomplete implementation, transitions may animate, and
         // not be completely synchronous.
-        Supplier<Pane> nextPaneSupplier = mPanes.get(paneId);
+        LazyOneshotSupplier<Pane> nextPaneSupplier = mPanes.get(paneId);
         if (nextPaneSupplier == null) return false;
 
         Pane nextPane = nextPaneSupplier.get();
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneManagerImplUnitTest.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneManagerImplUnitTest.java
index a549d164..728d194c 100644
--- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneManagerImplUnitTest.java
+++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/PaneManagerImplUnitTest.java
@@ -8,36 +8,42 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
 
 import androidx.test.filters.SmallTest;
 
-import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
+import org.chromium.base.supplier.LazyOneshotSupplier;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 
 /** Unit tests for {@link PaneManagerImpl}. */
 @RunWith(BaseRobolectricTestRunner.class)
 public class PaneManagerImplUnitTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Mock private Pane mTabSwitcherPane;
     @Mock private Pane mIncognitoTabSwitcherPane;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
+    @Mock private Supplier<Pane> mPaneSupplier;
 
     @Test
     @SmallTest
     public void testFocusChangesPane() {
         PaneListBuilder builder =
                 new PaneListBuilder(new DefaultPaneOrderController())
-                        .registerPane(PaneId.TAB_SWITCHER, () -> mTabSwitcherPane)
                         .registerPane(
-                                PaneId.INCOGNITO_TAB_SWITCHER, () -> mIncognitoTabSwitcherPane);
+                                PaneId.TAB_SWITCHER,
+                                LazyOneshotSupplier.fromValue(mTabSwitcherPane))
+                        .registerPane(
+                                PaneId.INCOGNITO_TAB_SWITCHER,
+                                LazyOneshotSupplier.fromValue(mIncognitoTabSwitcherPane));
         PaneManager paneManager = new PaneManagerImpl(builder);
 
         assertNull(paneManager.getFocusedPaneSupplier().get());
@@ -57,7 +63,9 @@
     public void testFocusUnregisteredPane() {
         PaneListBuilder builder =
                 new PaneListBuilder(new DefaultPaneOrderController())
-                        .registerPane(PaneId.TAB_SWITCHER, () -> mTabSwitcherPane);
+                        .registerPane(
+                                PaneId.TAB_SWITCHER,
+                                LazyOneshotSupplier.fromValue(mTabSwitcherPane));
         PaneManager paneManager = new PaneManagerImpl(builder);
 
         assertNull(paneManager.getFocusedPaneSupplier().get());
@@ -77,8 +85,10 @@
     public void testFocusUnsuppliedPane() {
         PaneListBuilder builder =
                 new PaneListBuilder(new DefaultPaneOrderController())
-                        .registerPane(PaneId.TAB_SWITCHER, () -> mTabSwitcherPane)
-                        .registerPane(PaneId.BOOKMARKS, () -> null);
+                        .registerPane(
+                                PaneId.TAB_SWITCHER,
+                                LazyOneshotSupplier.fromValue(mTabSwitcherPane))
+                        .registerPane(PaneId.BOOKMARKS, LazyOneshotSupplier.fromValue(null));
         PaneManager paneManager = new PaneManagerImpl(builder);
 
         assertNull(paneManager.getFocusedPaneSupplier().get());
@@ -92,4 +102,19 @@
         assertFalse(paneManager.focusPane(PaneId.BOOKMARKS));
         assertEquals(mTabSwitcherPane, paneManager.getFocusedPaneSupplier().get());
     }
+
+    @Test
+    @SmallTest
+    public void testPaneSuppliedLazily() {
+        PaneListBuilder builder =
+                new PaneListBuilder(new DefaultPaneOrderController())
+                        .registerPane(
+                                PaneId.TAB_SWITCHER,
+                                LazyOneshotSupplier.fromSupplier(mPaneSupplier));
+        PaneManager paneManager = new PaneManagerImpl(builder);
+        verifyNoInteractions(mPaneSupplier);
+
+        paneManager.focusPane(PaneId.TAB_SWITCHER);
+        verify(mPaneSupplier).get();
+    }
 }
diff --git a/chrome/browser/lacros/browser_service_lacros.cc b/chrome/browser/lacros/browser_service_lacros.cc
index 1f160956..7134cdff 100644
--- a/chrome/browser/lacros/browser_service_lacros.cc
+++ b/chrome/browser/lacros/browser_service_lacros.cc
@@ -425,6 +425,11 @@
       /*can_trigger_fre=*/true);
 }
 
+void BrowserServiceLacros::OpenProfileManager() {
+  ProfilePicker::Show(ProfilePicker::Params::FromEntryPoint(
+      ProfilePicker::EntryPoint::kProfileMenuManageProfiles));
+}
+
 void BrowserServiceLacros::OnSystemInformationReady(
     GetFeedbackDataCallback callback,
     std::unique_ptr<system_logs::SystemLogsResponse> sys_info) {
diff --git a/chrome/browser/lacros/browser_service_lacros.h b/chrome/browser/lacros/browser_service_lacros.h
index 6c5093fc..83731e82 100644
--- a/chrome/browser/lacros/browser_service_lacros.h
+++ b/chrome/browser/lacros/browser_service_lacros.h
@@ -64,6 +64,7 @@
   void NotifyPolicyFetchAttempt() override;
   void UpdateKeepAlive(bool enabled) override;
   void OpenForFullRestore(bool skip_crash_restore) override;
+  void OpenProfileManager() override;
 
  private:
   struct PendingOpenUrl;
diff --git a/chrome/browser/lacros/browser_service_lacros_browsertest.cc b/chrome/browser/lacros/browser_service_lacros_browsertest.cc
index 2c6d20d..2f42de5a 100644
--- a/chrome/browser/lacros/browser_service_lacros_browsertest.cc
+++ b/chrome/browser/lacros/browser_service_lacros_browsertest.cc
@@ -108,6 +108,8 @@
     Browser::Create(Browser::CreateParams(browser()->profile(), false));
   }
 
+  void OpenProfileManager() { browser_service()->OpenProfileManager(); }
+
   void VerifyFullscreenWindow() {
     // Verify the browser status.
     Browser* browser = BrowserList::GetInstance()->GetLastActive();
@@ -194,6 +196,20 @@
 }
 
 IN_PROC_BROWSER_TEST_F(BrowserServiceLacrosBrowserTest,
+                       OpenProfileManagerTest) {
+  // Keep the browser process running during the test while the browser is
+  // closed.
+  ScopedKeepAlive keep_alive(KeepAliveOrigin::BROWSER,
+                             KeepAliveRestartOption::DISABLED);
+  // Start in a state with no browser windows opened.
+  CloseBrowserSynchronously(browser());
+  EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
+  EXPECT_FALSE(ProfilePicker::IsOpen());
+  OpenProfileManager();
+  EXPECT_TRUE(ProfilePicker::IsOpen());
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserServiceLacrosBrowserTest,
                        NewWindow_OpensProfilePicker) {
   // Keep the browser process running during the test while the browser is
   // closed.
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/ContentLanguagesPreference.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/ContentLanguagesPreference.java
index 0f894f14..e9d08016 100644
--- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/ContentLanguagesPreference.java
+++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/ContentLanguagesPreference.java
@@ -78,48 +78,51 @@
             // Enable "Remove" option if there are multiple accept languages.
             menuItems.add(buildMenuListItem(R.string.remove, 0, 0, languageCount > 1));
 
-            // Add some appropriate options for moving the language when the list is not
-            // draggable. E.g. in the accessibility mode.
-            if (!mDragStateDelegate.getDragEnabled()) {
-                // Add "Move to top" and "Move up" menu when it's not the first one.
-                if (position > 0) {
-                    menuItems.add(buildMenuListItem(R.string.menu_item_move_to_top, 0, 0));
-                    menuItems.add(buildMenuListItem(R.string.menu_item_move_up, 0, 0));
-                }
-
-                // Add "Move down" menu when it's not the last one.
-                if (position < (languageCount - 1)) {
-                    menuItems.add(buildMenuListItem(R.string.menu_item_move_down, 0, 0));
-                }
+            // Add movement options even if not in accessibility mode https://crbug.com/1440469.
+            // Add "Move to top" and "Move up" menu when it's not the first one.
+            if (position > 0) {
+                menuItems.add(buildMenuListItem(R.string.menu_item_move_to_top, 0, 0));
+                menuItems.add(buildMenuListItem(R.string.menu_item_move_up, 0, 0));
             }
-            ListMenu.Delegate delegate = (model) -> {
-                int textId = model.get(ListMenuItemProperties.TITLE_ID);
-                if (textId == R.string.languages_item_option_offer_to_translate) {
-                    // Toggle current blocked state of this language.
-                    boolean state = model.get(ListMenuItemProperties.END_ICON_ID) == 0;
-                    TranslateBridge.setLanguageBlockedState(info.getCode(), !state);
-                    LanguagesManager.recordAction(state
-                                    ? LanguagesManager.LanguageSettingsActionType
-                                              .ENABLE_TRANSLATE_FOR_SINGLE_LANGUAGE
-                                    : LanguagesManager.LanguageSettingsActionType
-                                              .DISABLE_TRANSLATE_FOR_SINGLE_LANGUAGE);
-                } else if (textId == R.string.remove) {
-                    LanguagesManager.getInstance().removeFromAcceptLanguages(info.getCode());
-                    LanguagesManager.recordAction(
-                            LanguagesManager.LanguageSettingsActionType.LANGUAGE_REMOVED);
-                } else if (textId == R.string.menu_item_move_up) {
-                    LanguagesManager.getInstance().moveLanguagePosition(info.getCode(), -1, true);
-                } else if (textId == R.string.menu_item_move_down) {
-                    LanguagesManager.getInstance().moveLanguagePosition(info.getCode(), 1, true);
-                } else if (textId == R.string.menu_item_move_to_top) {
-                    LanguagesManager.getInstance().moveLanguagePosition(
-                            info.getCode(), -position, true);
-                }
-                // Re-generate list items.
-                if (textId != R.string.remove) {
-                    notifyDataSetChanged();
-                }
-            };
+
+            // Add "Move down" menu when it's not the last one.
+            if (position < (languageCount - 1)) {
+                menuItems.add(buildMenuListItem(R.string.menu_item_move_down, 0, 0));
+            }
+
+            ListMenu.Delegate delegate =
+                    (model) -> {
+                        int textId = model.get(ListMenuItemProperties.TITLE_ID);
+                        if (textId == R.string.languages_item_option_offer_to_translate) {
+                            // Toggle current blocked state of this language.
+                            boolean state = model.get(ListMenuItemProperties.END_ICON_ID) == 0;
+                            TranslateBridge.setLanguageBlockedState(info.getCode(), !state);
+                            LanguagesManager.recordAction(
+                                    state
+                                            ? LanguagesManager.LanguageSettingsActionType
+                                                    .ENABLE_TRANSLATE_FOR_SINGLE_LANGUAGE
+                                            : LanguagesManager.LanguageSettingsActionType
+                                                    .DISABLE_TRANSLATE_FOR_SINGLE_LANGUAGE);
+                        } else if (textId == R.string.remove) {
+                            LanguagesManager.getInstance()
+                                    .removeFromAcceptLanguages(info.getCode());
+                            LanguagesManager.recordAction(
+                                    LanguagesManager.LanguageSettingsActionType.LANGUAGE_REMOVED);
+                        } else if (textId == R.string.menu_item_move_up) {
+                            LanguagesManager.getInstance()
+                                    .moveLanguagePosition(info.getCode(), -1, true);
+                        } else if (textId == R.string.menu_item_move_down) {
+                            LanguagesManager.getInstance()
+                                    .moveLanguagePosition(info.getCode(), 1, true);
+                        } else if (textId == R.string.menu_item_move_to_top) {
+                            LanguagesManager.getInstance()
+                                    .moveLanguagePosition(info.getCode(), -position, true);
+                        }
+                        // Re-generate list items.
+                        if (textId != R.string.remove) {
+                            notifyDataSetChanged();
+                        }
+                    };
             ((LanguageRowViewHolder) holder)
                     .setMenuButtonDelegate(
                             () -> {
diff --git a/chrome/browser/media/BUILD.gn b/chrome/browser/media/BUILD.gn
index 801df99..41d1143 100644
--- a/chrome/browser/media/BUILD.gn
+++ b/chrome/browser/media/BUILD.gn
@@ -16,7 +16,6 @@
     "//url/mojom:url_mojom_origin",
   ]
   webui_module_path = "/"
-  use_typescript_sources = true
 }
 
 proto_library("media_engagement_preload_proto") {
diff --git a/chrome/browser/media/webrtc/webrtc_log_uploader.cc b/chrome/browser/media/webrtc/webrtc_log_uploader.cc
index a26418e..793c583e 100644
--- a/chrome/browser/media/webrtc/webrtc_log_uploader.cc
+++ b/chrome/browser/media/webrtc/webrtc_log_uploader.cc
@@ -89,6 +89,10 @@
 
 }  // namespace
 
+BASE_FEATURE(kWebRTCLogUploadSuffix,
+             "WebRTCLogUploadSuffix",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 WebRtcLogUploader::UploadDoneData::UploadDoneData() = default;
 WebRtcLogUploader::UploadDoneData::UploadDoneData(
     WebRtcLogUploader::UploadDoneData&& other) = default;
@@ -377,11 +381,18 @@
 #else
 #error Platform not supported.
 #endif
-  net::AddMultipartValueForUpload("prod", product, kWebrtcLogMultipartBoundary,
-                                  "", post_data);
   net::AddMultipartValueForUpload(
-      "ver", base::StrCat({version_info::GetVersionNumber(), "-webrtc"}),
+      "prod",
+      (base::FeatureList::IsEnabled(kWebRTCLogUploadSuffix)
+           ? base::StrCat({product, "_webrtc"})
+           : product),
       kWebrtcLogMultipartBoundary, "", post_data);
+  std::string version(
+      base::FeatureList::IsEnabled(kWebRTCLogUploadSuffix)
+          ? version_info::GetVersionNumber()
+          : base::StrCat({version_info::GetVersionNumber(), "-webrtc"}));
+  net::AddMultipartValueForUpload("ver", version, kWebrtcLogMultipartBoundary,
+                                  "", post_data);
   net::AddMultipartValueForUpload("guid", "0", kWebrtcLogMultipartBoundary, "",
                                   post_data);
   net::AddMultipartValueForUpload("type", "webrtc_log",
diff --git a/chrome/browser/media/webrtc/webrtc_log_uploader.h b/chrome/browser/media/webrtc/webrtc_log_uploader.h
index 4445543..4fd754f 100644
--- a/chrome/browser/media/webrtc/webrtc_log_uploader.h
+++ b/chrome/browser/media/webrtc/webrtc_log_uploader.h
@@ -12,6 +12,7 @@
 #include <memory>
 #include <string>
 
+#include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
@@ -46,6 +47,8 @@
   };
 };
 
+BASE_DECLARE_FEATURE(kWebRTCLogUploadSuffix);
+
 // WebRtcLogUploader uploads WebRTC logs, keeps count of how many logs have
 // been started and denies further logs if a limit is reached. It also adds
 // the timestamp and report ID of the uploded log to a text file. There must
diff --git a/chrome/browser/media/webrtc/webrtc_log_uploader_unittest.cc b/chrome/browser/media/webrtc/webrtc_log_uploader_unittest.cc
index c22aeaa..057da576d 100644
--- a/chrome/browser/media/webrtc/webrtc_log_uploader_unittest.cc
+++ b/chrome/browser/media/webrtc/webrtc_log_uploader_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/task/sequenced_task_runner.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_future.h"
 #include "base/time/time.h"
@@ -174,6 +175,27 @@
     EXPECT_EQ(dump_content, lines[i + 3]);
   }
 
+  std::string GetValueFromMultipart(const std::string& post_data,
+                                    const std::string& value_name) {
+    std::vector<std::string> lines = base::SplitStringUsingSubstr(
+        post_data, "\r\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+
+    std::string name_line = "Content-Disposition: form-data; name=\"";
+    name_line.append(value_name);
+    name_line.append("\"");
+
+    size_t i = 0;
+    for (; i < lines.size(); ++i) {
+      if (lines[i] == name_line) {
+        break;
+      }
+    }
+
+    EXPECT_LT(i, lines.size() - 2);
+
+    return lines[i + 2];
+  }
+
   static void AddLocallyStoredLogInfoToUploadListFile(
       WebRtcLogUploader* log_uploader,
       const base::FilePath& upload_list_path,
@@ -357,3 +379,75 @@
   webrtc_log_uploader->Shutdown();
   FlushRunLoop();
 }
+
+TEST_F(WebRtcLogUploaderTest, ProductHasNoSuffixWithoutFeature) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  std::string post_data;
+  auto webrtc_log_uploader = std::make_unique<WebRtcLogUploader>();
+  webrtc_log_uploader->OverrideUploadWithBufferForTesting(&post_data);
+
+  WebRtcLogUploader::UploadDoneData upload_done_data;
+  upload_done_data.paths.directory = temp_dir.GetPath().AppendASCII("log");
+
+  std::unique_ptr<WebRtcLogBuffer> log(new WebRtcLogBuffer());
+  log->SetComplete();
+
+  base::RunLoop run_loop;
+  webrtc_log_uploader->background_task_runner()->PostTaskAndReply(
+      FROM_HERE,
+      base::BindOnce(&WebRtcLogUploader::OnLoggingStopped,
+                     base::Unretained(webrtc_log_uploader.get()),
+                     std::move(log), std::make_unique<WebRtcLogMetaDataMap>(),
+                     std::move(upload_done_data),
+                     /*is_text_log_upload_allowed=*/true),
+      run_loop.QuitClosure());
+  run_loop.Run();
+
+  // Version should have a webrtc suffix, Product should not.
+  EXPECT_EQ(GetValueFromMultipart(post_data, "prod").find("_webrtc"),
+            std::string::npos);
+  EXPECT_NE(GetValueFromMultipart(post_data, "ver").find("-webrtc"),
+            std::string::npos);
+
+  webrtc_log_uploader->Shutdown();
+  FlushRunLoop();
+}
+
+TEST_F(WebRtcLogUploaderTest, ProductHasSuffixWithFeature) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(kWebRTCLogUploadSuffix);
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  std::string post_data;
+  auto webrtc_log_uploader = std::make_unique<WebRtcLogUploader>();
+  webrtc_log_uploader->OverrideUploadWithBufferForTesting(&post_data);
+
+  WebRtcLogUploader::UploadDoneData upload_done_data;
+  upload_done_data.paths.directory = temp_dir.GetPath().AppendASCII("log");
+
+  std::unique_ptr<WebRtcLogBuffer> log(new WebRtcLogBuffer());
+  log->SetComplete();
+
+  base::RunLoop run_loop;
+  webrtc_log_uploader->background_task_runner()->PostTaskAndReply(
+      FROM_HERE,
+      base::BindOnce(&WebRtcLogUploader::OnLoggingStopped,
+                     base::Unretained(webrtc_log_uploader.get()),
+                     std::move(log), std::make_unique<WebRtcLogMetaDataMap>(),
+                     std::move(upload_done_data),
+                     /*is_text_log_upload_allowed=*/true),
+      run_loop.QuitClosure());
+  run_loop.Run();
+
+  // Product should have a webrtc suffix, Version should not.
+  EXPECT_NE(GetValueFromMultipart(post_data, "prod").find("_webrtc"),
+            std::string::npos);
+  EXPECT_EQ(GetValueFromMultipart(post_data, "ver").find("-webrtc"),
+            std::string::npos);
+
+  webrtc_log_uploader->Shutdown();
+  FlushRunLoop();
+}
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
index 682144f..963920c 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
@@ -443,15 +443,6 @@
   EXPECT_EQ(1u, entries.size());
 }
 
-// Disabled because it fails when SingleProcessMash feature is enabled. Since
-// Navigation Predictor is not going to be enabled on Chrome OS, disabling the
-// browser test on that platform is fine.
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-#define DISABLE_ON_CHROMEOS(x) DISABLED_##x
-#else
-#define DISABLE_ON_CHROMEOS(x) x
-#endif
-
 class NavigationPredictorBrowserTestWithDefaultPredictorEnabled
     : public NavigationPredictorBrowserTest {
  public:
diff --git a/chrome/browser/nearby_sharing/nearby_connection_impl.cc b/chrome/browser/nearby_sharing/nearby_connection_impl.cc
index 4783ddc..273dadb 100644
--- a/chrome/browser/nearby_sharing/nearby_connection_impl.cc
+++ b/chrome/browser/nearby_sharing/nearby_connection_impl.cc
@@ -8,7 +8,7 @@
 #include "crypto/random.h"
 
 NearbyConnectionImpl::NearbyConnectionImpl(
-    NearbyConnectionsManager* nearby_connections_manager,
+    base::WeakPtr<NearbyConnectionsManager> nearby_connections_manager,
     const std::string& endpoint_id)
     : nearby_connections_manager_(nearby_connections_manager),
       endpoint_id_(endpoint_id) {}
diff --git a/chrome/browser/nearby_sharing/nearby_connection_impl.h b/chrome/browser/nearby_sharing/nearby_connection_impl.h
index 0686e4e..287bb84 100644
--- a/chrome/browser/nearby_sharing/nearby_connection_impl.h
+++ b/chrome/browser/nearby_sharing/nearby_connection_impl.h
@@ -18,8 +18,9 @@
 
 class NearbyConnectionImpl : public NearbyConnection {
  public:
-  NearbyConnectionImpl(NearbyConnectionsManager* nearby_connections_manager,
-                       const std::string& endpoint_id);
+  NearbyConnectionImpl(
+      base::WeakPtr<NearbyConnectionsManager> nearby_connections_manager,
+      const std::string& endpoint_id);
   ~NearbyConnectionImpl() override;
 
   // NearbyConnection:
@@ -37,8 +38,7 @@
 
   SEQUENCE_CHECKER(sequence_checker_);
 
-  raw_ptr<NearbyConnectionsManager, ExperimentalAsh>
-      nearby_connections_manager_;
+  base::WeakPtr<NearbyConnectionsManager> nearby_connections_manager_;
   std::string endpoint_id_;
   ReadCallback read_callback_;
   base::OnceClosure disconnect_listener_;
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc
index dcc0fd0..b03acc3a 100644
--- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc
+++ b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc
@@ -640,7 +640,8 @@
     }
 
     auto result = connections_.emplace(
-        endpoint_id, std::make_unique<NearbyConnectionImpl>(this, endpoint_id));
+        endpoint_id, std::make_unique<NearbyConnectionImpl>(
+                         weak_ptr_factory_.GetWeakPtr(), endpoint_id));
     DCHECK(result.second);
     incoming_connection_listener_->OnIncomingConnectionAccepted(
         endpoint_id, it->second->endpoint_info, result.first->second.get());
@@ -652,7 +653,8 @@
     }
 
     auto result = connections_.emplace(
-        endpoint_id, std::make_unique<NearbyConnectionImpl>(this, endpoint_id));
+        endpoint_id, std::make_unique<NearbyConnectionImpl>(
+                         weak_ptr_factory_.GetWeakPtr(), endpoint_id));
     DCHECK(result.second);
     std::move(pending_it->second).Run(result.first->second.get());
     pending_outgoing_connections_.erase(pending_it);
@@ -689,9 +691,10 @@
   // Destroying the NearbyConnectionImpl object may start a chain of callbacks
   // that can delete this NearbyConnectionsManagerImpl object. This may result
   // in a crash (see b/303675257). Update the |connections_| map, but wait to
-  // destroy the connection object until after this NearbyConnectionsManagerImpl
-  // object is no longer in use.
-  auto connection = std::move(connections_[endpoint_id]);
+  // destroy the connection object until after we're done modifying internal
+  // state in OnDisconnected() by letting the connection go out of scope.
+  std::unique_ptr<NearbyConnectionImpl> connection =
+      std::move(connections_[endpoint_id]);
   connections_.erase(endpoint_id);
 
   if (base::Contains(requested_bwu_endpoint_ids_, endpoint_id)) {
@@ -702,10 +705,6 @@
   requested_bwu_endpoint_ids_.erase(endpoint_id);
   on_bandwidth_changed_endpoint_ids_.erase(endpoint_id);
   current_upgraded_mediums_.erase(endpoint_id);
-
-  // The NearbyConnectionImpl object may now be safely destroyed.
-  connection.reset();
-  // TODO(crbug/1111458): Support TransferManager.
 }
 
 void NearbyConnectionsManagerImpl::OnBandwidthChanged(
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc
index 9ce5bff..d0bbc318d 100644
--- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc
+++ b/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc
@@ -139,6 +139,9 @@
 class NearbyConnectionsManagerImplTest : public testing::Test {
  public:
   void SetUp() override {
+    nearby_connections_manager_ =
+        std::make_unique<NearbyConnectionsManagerImpl>(&nearby_process_manager_,
+                                                       kServiceId);
     scoped_feature_list_.InitAndEnableFeature(features::kNearbySharingWebRtc);
 
     EXPECT_CALL(nearby_process_manager_, GetNearbyProcessReference)
@@ -193,8 +196,8 @@
           run_loop.Quit();
         });
 
-    nearby_connections_manager_.StartDiscovery(&discovery_listener, data_usage,
-                                               std::move(callback));
+    nearby_connections_manager_->StartDiscovery(&discovery_listener, data_usage,
+                                                std::move(callback));
 
     run_loop.Run();
   }
@@ -226,7 +229,7 @@
           EXPECT_EQ(status, Status::kSuccess);
           run_loop.Quit();
         });
-    nearby_connections_manager_.StartAdvertising(
+    nearby_connections_manager_->StartAdvertising(
         local_endpoint_info, &incoming_connection_listener,
         PowerLevel::kHighPower, DataUsage::kOnline, std::move(callback));
     run_loop.Run();
@@ -264,7 +267,7 @@
 
     base::RunLoop run_loop;
     NearbyConnection* nearby_connection;
-    nearby_connections_manager_.Connect(
+    nearby_connections_manager_->Connect(
         local_endpoint_info, kRemoteEndpointId,
         /*bluetooth_mac_address=*/absl::nullopt, DataUsage::kOffline,
         base::BindLambdaForTesting([&](NearbyConnection* connection) {
@@ -357,7 +360,7 @@
     incoming_connection_run_loop.Run();
 
     EXPECT_EQ(raw_authentication_token,
-              nearby_connections_manager_.GetRawAuthenticationToken(
+              nearby_connections_manager_->GetRawAuthenticationToken(
                   kRemoteEndpointId));
 
     return nearby_connection;
@@ -396,7 +399,7 @@
           run_loop.Quit();
         });
 
-    nearby_connections_manager_.Send(
+    nearby_connections_manager_->Send(
         kRemoteEndpointId,
         Payload::New(payload_id, PayloadContent::NewFile(
                                      FilePayload::New(std::move(file)))),
@@ -416,8 +419,7 @@
   testing::NiceMock<ash::nearby::MockNearbyConnections> nearby_connections_;
   testing::NiceMock<ash::nearby::MockNearbyProcessManager>
       nearby_process_manager_;
-  NearbyConnectionsManagerImpl nearby_connections_manager_{
-      &nearby_process_manager_, kServiceId};
+  std::unique_ptr<NearbyConnectionsManagerImpl> nearby_connections_manager_;
 };
 
 TEST_F(NearbyConnectionsManagerImplTest, DiscoveryFlow) {
@@ -476,7 +478,7 @@
         std::move(callback).Run(Status::kSuccess);
         stop_discovery_run_loop.Quit();
       });
-  nearby_connections_manager_.StopDiscovery();
+  nearby_connections_manager_->StopDiscovery();
   stop_discovery_run_loop.Run();
 
   // StartDiscovery again will succeed.
@@ -504,7 +506,7 @@
   StartDiscovery(listener_remote, discovery_listener);
 
   EXPECT_CALL(nearby_connections_, StopAllEndpoints).Times(0);
-  nearby_connections_manager_.OnNearbyProcessStopped(
+  nearby_connections_manager_->OnNearbyProcessStopped(
       ash::nearby::NearbyProcessManager::NearbyProcessShutdownReason::kNormal);
 
   // Invoking OnEndpointFound will do nothing.
@@ -516,7 +518,7 @@
 
 TEST_F(NearbyConnectionsManagerImplTest, StopDiscoveryBeforeStart) {
   EXPECT_CALL(nearby_connections_, StopDiscovery).Times(0);
-  nearby_connections_manager_.StopDiscovery();
+  nearby_connections_manager_->StopDiscovery();
 }
 
 /******************************************************************************/
@@ -597,9 +599,9 @@
             run_loop.Quit();
           });
 
-  nearby_connections_manager_.Connect(local_endpoint_info, kRemoteEndpointId,
-                                      /*bluetooth_mac_address=*/absl::nullopt,
-                                      data_usage, base::DoNothing());
+  nearby_connections_manager_->Connect(local_endpoint_info, kRemoteEndpointId,
+                                       /*bluetooth_mac_address=*/absl::nullopt,
+                                       data_usage, base::DoNothing());
 
   run_loop.Run();
 }
@@ -668,9 +670,9 @@
             run_loop.Quit();
           });
 
-  nearby_connections_manager_.Connect(local_endpoint_info, kRemoteEndpointId,
-                                      GetParam().bluetooth_mac_address,
-                                      DataUsage::kOffline, base::DoNothing());
+  nearby_connections_manager_->Connect(local_endpoint_info, kRemoteEndpointId,
+                                       GetParam().bluetooth_mac_address,
+                                       DataUsage::kOffline, base::DoNothing());
 
   run_loop.Run();
 }
@@ -696,8 +698,8 @@
       Connect(connection_listener_remote, payload_listener_remote,
               ConnectionResponse::kRejceted);
   EXPECT_FALSE(nearby_connection);
-  EXPECT_FALSE(
-      nearby_connections_manager_.GetRawAuthenticationToken(kRemoteEndpointId));
+  EXPECT_FALSE(nearby_connections_manager_->GetRawAuthenticationToken(
+      kRemoteEndpointId));
 }
 
 TEST_F(NearbyConnectionsManagerImplTest, ConnectDisconnected) {
@@ -713,8 +715,8 @@
       Connect(connection_listener_remote, payload_listener_remote,
               ConnectionResponse::kDisconnected);
   EXPECT_FALSE(nearby_connection);
-  EXPECT_FALSE(
-      nearby_connections_manager_.GetRawAuthenticationToken(kRemoteEndpointId));
+  EXPECT_FALSE(nearby_connections_manager_->GetRawAuthenticationToken(
+      kRemoteEndpointId));
 }
 
 TEST_F(NearbyConnectionsManagerImplTest, ConnectAccepted) {
@@ -733,9 +735,9 @@
       Connect(connection_listener_remote, payload_listener_remote,
               ConnectionResponse::kAccepted);
   EXPECT_TRUE(nearby_connection);
-  EXPECT_EQ(
-      raw_authentication_token,
-      nearby_connections_manager_.GetRawAuthenticationToken(kRemoteEndpointId));
+  EXPECT_EQ(raw_authentication_token,
+            nearby_connections_manager_->GetRawAuthenticationToken(
+                kRemoteEndpointId));
 }
 
 TEST_F(NearbyConnectionsManagerImplTest, ConnectReadBeforeAppend) {
@@ -905,8 +907,8 @@
   read_run_loop_3.Run();
   disconnect_run_loop.Run();
 
-  EXPECT_FALSE(
-      nearby_connections_manager_.GetRawAuthenticationToken(kRemoteEndpointId));
+  EXPECT_FALSE(nearby_connections_manager_->GetRawAuthenticationToken(
+      kRemoteEndpointId));
 }
 
 TEST_F(NearbyConnectionsManagerImplTest, ConnectClosedByRemote) {
@@ -938,8 +940,8 @@
   close_run_loop.Run();
   read_run_loop.Run();
 
-  EXPECT_FALSE(
-      nearby_connections_manager_.GetRawAuthenticationToken(kRemoteEndpointId));
+  EXPECT_FALSE(nearby_connections_manager_->GetRawAuthenticationToken(
+      kRemoteEndpointId));
 }
 
 TEST_F(NearbyConnectionsManagerImplTest, ConnectClosedByClient) {
@@ -977,13 +979,13 @@
             std::move(callback).Run(Status::kSuccess);
             disconnect_run_loop.Quit();
           });
-  nearby_connections_manager_.Disconnect(kRemoteEndpointId);
+  nearby_connections_manager_->Disconnect(kRemoteEndpointId);
   close_run_loop.Run();
   read_run_loop.Run();
   disconnect_run_loop.Run();
 
-  EXPECT_FALSE(
-      nearby_connections_manager_.GetRawAuthenticationToken(kRemoteEndpointId));
+  EXPECT_FALSE(nearby_connections_manager_->GetRawAuthenticationToken(
+      kRemoteEndpointId));
 }
 
 TEST_F(NearbyConnectionsManagerImplTest, ConnectSendPayload) {
@@ -1055,7 +1057,7 @@
         payload_run_loop.Quit();
       });
 
-  nearby_connections_manager_.Cancel(kPayloadId);
+  nearby_connections_manager_->Cancel(kPayloadId);
   payload_run_loop.Run();
   cancel_run_loop.Run();
 }
@@ -1123,8 +1125,8 @@
         payload_run_loop.Quit();
       });
 
-  nearby_connections_manager_.Cancel(kPayloadId);
-  nearby_connections_manager_.Cancel(kPayloadId2);
+  nearby_connections_manager_->Cancel(kPayloadId);
+  nearby_connections_manager_->Cancel(kPayloadId2);
   payload_run_loop.Run();
   cancel_run_loop.Run();
 }
@@ -1168,7 +1170,7 @@
 
   base::RunLoop run_loop;
   NearbyConnection* nearby_connection = nullptr;
-  nearby_connections_manager_.Connect(
+  nearby_connections_manager_->Connect(
       local_endpoint_info, kRemoteEndpointId,
       /*bluetooth_mac_address=*/absl::nullopt, DataUsage::kOffline,
       base::BindLambdaForTesting([&](NearbyConnection* connection) {
@@ -1212,7 +1214,7 @@
   EXPECT_TRUE(connection);
 
   testing::NiceMock<MockPayloadStatusListener> payload_listener;
-  nearby_connections_manager_.RegisterPayloadStatusListener(
+  nearby_connections_manager_->RegisterPayloadStatusListener(
       kPayloadId, payload_listener.GetWeakPtr());
 
   auto expected_update = PayloadTransferUpdate::New(
@@ -1275,11 +1277,11 @@
   // to ensure control-frame logic is not invoked for either.
   auto payload_listener =
       std::make_unique<testing::NiceMock<MockPayloadStatusListener>>();
-  nearby_connections_manager_.RegisterPayloadStatusListener(
+  nearby_connections_manager_->RegisterPayloadStatusListener(
       kPayloadId, payload_listener->GetWeakPtr());
-  nearby_connections_manager_.RegisterPayloadStatusListener(
+  nearby_connections_manager_->RegisterPayloadStatusListener(
       kPayloadId2, payload_listener->GetWeakPtr());
-  nearby_connections_manager_.RegisterPayloadStatusListener(
+  nearby_connections_manager_->RegisterPayloadStatusListener(
       kPayloadId3, payload_listener->GetWeakPtr());
   base::File file1, file2;
   InitializeTemporaryFile(file1);
@@ -1388,8 +1390,8 @@
         register_payload_run_loop.Quit();
       });
 
-  nearby_connections_manager_.RegisterPayloadPath(kPayloadId, path,
-                                                  std::move(callback));
+  nearby_connections_manager_->RegisterPayloadPath(kPayloadId, path,
+                                                   std::move(callback));
 
   register_payload_run_loop.Run();
 }
@@ -1407,7 +1409,7 @@
   EXPECT_TRUE(connection);
 
   testing::NiceMock<MockPayloadStatusListener> payload_listener;
-  nearby_connections_manager_.RegisterPayloadStatusListener(
+  nearby_connections_manager_->RegisterPayloadStatusListener(
       kPayloadId, payload_listener.GetWeakPtr());
 
   const std::vector<uint8_t> expected_payload(std::begin(kPayload),
@@ -1428,7 +1430,8 @@
                                  kTotalSize, /*bytes_transferred=*/kTotalSize));
   payload_run_loop.Run();
 
-  Payload* payload = nearby_connections_manager_.GetIncomingPayload(kPayloadId);
+  Payload* payload =
+      nearby_connections_manager_->GetIncomingPayload(kPayloadId);
   ASSERT_TRUE(payload);
   ASSERT_TRUE(payload->content->is_bytes());
   EXPECT_EQ(expected_payload, payload->content->get_bytes()->bytes);
@@ -1447,7 +1450,7 @@
   EXPECT_TRUE(connection);
 
   testing::NiceMock<MockPayloadStatusListener> payload_listener;
-  nearby_connections_manager_.RegisterPayloadStatusListener(
+  nearby_connections_manager_->RegisterPayloadStatusListener(
       kPayloadId, payload_listener.GetWeakPtr());
 
   const std::vector<uint8_t> expected_payload(std::begin(kPayload),
@@ -1474,7 +1477,7 @@
   {
     base::ScopedAllowBlockingForTesting allow_blocking;
     Payload* payload =
-        nearby_connections_manager_.GetIncomingPayload(kPayloadId);
+        nearby_connections_manager_->GetIncomingPayload(kPayloadId);
     ASSERT_TRUE(payload);
     ASSERT_TRUE(payload->content->is_file());
     std::vector<uint8_t> payload_bytes(
@@ -1498,7 +1501,7 @@
   EXPECT_TRUE(connection);
 
   testing::NiceMock<MockPayloadStatusListener> payload_listener;
-  nearby_connections_manager_.RegisterPayloadStatusListener(
+  nearby_connections_manager_->RegisterPayloadStatusListener(
       kPayloadId, payload_listener.GetWeakPtr());
 
   base::File file;
@@ -1518,9 +1521,9 @@
                                  kTotalSize, /*bytes_transferred=*/kTotalSize));
   payload_run_loop.Run();
 
-  nearby_connections_manager_.ClearIncomingPayloads();
+  nearby_connections_manager_->ClearIncomingPayloads();
 
-  EXPECT_FALSE(nearby_connections_manager_.GetIncomingPayload(kPayloadId));
+  EXPECT_FALSE(nearby_connections_manager_->GetIncomingPayload(kPayloadId));
 }
 
 /******************************************************************************/
@@ -1589,7 +1592,7 @@
         std::move(callback).Run(Status::kSuccess);
       });
 
-  nearby_connections_manager_.StartAdvertising(
+  nearby_connections_manager_->StartAdvertising(
       local_endpoint_info, &incoming_connection_listener, power_level,
       data_usage, std::move(callback));
 
@@ -1614,7 +1617,7 @@
 
 TEST_F(NearbyConnectionsManagerImplTest, StopAdvertising_BeforeStart) {
   EXPECT_CALL(nearby_connections_, StopAdvertising).Times(0);
-  nearby_connections_manager_.StopAdvertising(base::BindOnce(
+  nearby_connections_manager_->StopAdvertising(base::BindOnce(
       [](Status status) { EXPECT_EQ(status, Status::kSuccess); }));
 }
 
@@ -1632,7 +1635,7 @@
         std::move(callback).Run(Status::kSuccess);
         run_loop.Quit();
       });
-  nearby_connections_manager_.StopAdvertising(base::BindOnce(
+  nearby_connections_manager_->StopAdvertising(base::BindOnce(
       [](Status status) { EXPECT_EQ(status, Status::kSuccess); }));
   run_loop.Run();
 }
@@ -1652,7 +1655,7 @@
             std::move(callback).Run(Status::kSuccess);
             run_loop.Quit();
           });
-  nearby_connections_manager_.Shutdown();
+  nearby_connections_manager_->Shutdown();
   run_loop.Run();
 }
 
@@ -1671,7 +1674,7 @@
             shutdown_run_loop.Quit();
           });
 
-  nearby_connections_manager_.Shutdown();
+  nearby_connections_manager_->Shutdown();
   shutdown_run_loop.Run();
 
   // RequestConnection will fail.
@@ -1679,7 +1682,7 @@
                                                  std::end(kEndpointInfo));
   base::RunLoop connect_run_loop;
   NearbyConnection* nearby_connection;
-  nearby_connections_manager_.Connect(
+  nearby_connections_manager_->Connect(
       local_endpoint_info, kRemoteEndpointId,
       /*bluetooth_mac_address=*/absl::nullopt, DataUsage::kOffline,
       base::BindLambdaForTesting([&](NearbyConnection* connection) {
@@ -1694,7 +1697,7 @@
 TEST_F(NearbyConnectionsManagerImplTest,
        ShutdownBeforeStartDiscoveryOrAdvertising) {
   EXPECT_CALL(nearby_connections_, StopAllEndpoints).Times(0);
-  nearby_connections_manager_.Shutdown();
+  nearby_connections_manager_->Shutdown();
 }
 
 TEST_F(NearbyConnectionsManagerImplTest,
@@ -1716,7 +1719,7 @@
         std::move(callback).Run(Status::kSuccess);
         run_loop.Quit();
       });
-  nearby_connections_manager_.UpgradeBandwidth(kRemoteEndpointId);
+  nearby_connections_manager_->UpgradeBandwidth(kRemoteEndpointId);
   run_loop.Run();
 }
 
@@ -1747,14 +1750,14 @@
         std::move(callback).Run(Status::kSuccess);
         run_loop.Quit();
       });
-  nearby_connections_manager_.UpgradeBandwidth(kRemoteEndpointId);
+  nearby_connections_manager_->UpgradeBandwidth(kRemoteEndpointId);
   run_loop.Run();
 }
 
 TEST_F(NearbyConnectionsManagerImplTest,
        UpgradeBandwidthBeforeStartDiscoveryOrAdvertising) {
   EXPECT_CALL(nearby_connections_, InitiateBandwidthUpgrade).Times(0);
-  nearby_connections_manager_.UpgradeBandwidth(kRemoteEndpointId);
+  nearby_connections_manager_->UpgradeBandwidth(kRemoteEndpointId);
 }
 
 TEST_F(NearbyConnectionsManagerImplTest,
@@ -1769,5 +1772,30 @@
 
   // Bandwidth upgrade should not be attempted if WebRTC is disabled.
   EXPECT_CALL(nearby_connections_, InitiateBandwidthUpgrade).Times(0);
-  nearby_connections_manager_.UpgradeBandwidth(kRemoteEndpointId);
+  nearby_connections_manager_->UpgradeBandwidth(kRemoteEndpointId);
+}
+
+// Regression test for b/303675257.
+TEST_F(NearbyConnectionsManagerImplTest,
+       DisconnectListenerDeletesNearbyConnectionsManager) {
+  // StartDiscovery will succeed.
+  mojo::Remote<EndpointDiscoveryListener> discovery_listener_remote;
+  testing::NiceMock<MockDiscoveryListener> discovery_listener;
+  StartDiscovery(discovery_listener_remote, discovery_listener);
+
+  // RequestConnection will succeed.
+  mojo::Remote<ConnectionLifecycleListener> connection_listener_remote;
+  mojo::Remote<PayloadListener> payload_listener_remote;
+  NearbyConnection* nearby_connection =
+      Connect(connection_listener_remote, payload_listener_remote,
+              ConnectionResponse::kAccepted);
+  ASSERT_TRUE(nearby_connection);
+  EXPECT_NE(nullptr, nearby_connections_manager_);
+
+  // Close should invoke disconnection callback.
+  nearby_connection->SetDisconnectionListener(base::BindLambdaForTesting(
+      [&]() { nearby_connections_manager_.reset(); }));
+
+  nearby_connection->Close();
+  EXPECT_EQ(nullptr, nearby_connections_manager_);
 }
diff --git a/chrome/browser/new_tab_page/modules/drive/BUILD.gn b/chrome/browser/new_tab_page/modules/drive/BUILD.gn
index 362f086..c0d942a 100644
--- a/chrome/browser/new_tab_page/modules/drive/BUILD.gn
+++ b/chrome/browser/new_tab_page/modules/drive/BUILD.gn
@@ -9,6 +9,5 @@
 mojom("mojo_bindings") {
   sources = [ "drive.mojom" ]
   webui_module_path = "/"
-  use_typescript_sources = true
   public_deps = [ "//url/mojom:url_mojom_gurl" ]
 }
diff --git a/chrome/browser/new_tab_page/modules/feed/BUILD.gn b/chrome/browser/new_tab_page/modules/feed/BUILD.gn
index 625e0ba..3c1aee9 100644
--- a/chrome/browser/new_tab_page/modules/feed/BUILD.gn
+++ b/chrome/browser/new_tab_page/modules/feed/BUILD.gn
@@ -7,7 +7,6 @@
 mojom("mojo_bindings") {
   sources = [ "feed.mojom" ]
   webui_module_path = "/"
-  use_typescript_sources = true
   public_deps = [
     "//mojo/public/mojom/base",
     "//url/mojom:url_mojom_gurl",
diff --git a/chrome/browser/new_tab_page/modules/history_clusters/BUILD.gn b/chrome/browser/new_tab_page/modules/history_clusters/BUILD.gn
index f74d4324..ee2270ac 100644
--- a/chrome/browser/new_tab_page/modules/history_clusters/BUILD.gn
+++ b/chrome/browser/new_tab_page/modules/history_clusters/BUILD.gn
@@ -10,7 +10,6 @@
     "history_clusters_layout_type.mojom",
   ]
   webui_module_path = "/"
-  use_typescript_sources = true
   public_deps = [
     "//chrome/browser/new_tab_page/modules/history_clusters/cart:mojo_bindings",
     "//chrome/browser/new_tab_page/modules/history_clusters/discount:mojo_bindings",
diff --git a/chrome/browser/new_tab_page/modules/history_clusters/cart/BUILD.gn b/chrome/browser/new_tab_page/modules/history_clusters/cart/BUILD.gn
index 78fd6374..a4be2a1 100644
--- a/chrome/browser/new_tab_page/modules/history_clusters/cart/BUILD.gn
+++ b/chrome/browser/new_tab_page/modules/history_clusters/cart/BUILD.gn
@@ -8,5 +8,4 @@
   sources = [ "cart.mojom" ]
   public_deps = [ "//url/mojom:url_mojom_gurl" ]
   webui_module_path = "/"
-  use_typescript_sources = true
 }
diff --git a/chrome/browser/new_tab_page/modules/history_clusters/discount/BUILD.gn b/chrome/browser/new_tab_page/modules/history_clusters/discount/BUILD.gn
index fa2e6a2bc..0ca49ca 100644
--- a/chrome/browser/new_tab_page/modules/history_clusters/discount/BUILD.gn
+++ b/chrome/browser/new_tab_page/modules/history_clusters/discount/BUILD.gn
@@ -8,5 +8,4 @@
   sources = [ "discount.mojom" ]
   public_deps = [ "//url/mojom:url_mojom_gurl" ]
   webui_module_path = "/"
-  use_typescript_sources = true
 }
diff --git a/chrome/browser/new_tab_page/modules/photos/BUILD.gn b/chrome/browser/new_tab_page/modules/photos/BUILD.gn
index c2dfa31..201d313 100644
--- a/chrome/browser/new_tab_page/modules/photos/BUILD.gn
+++ b/chrome/browser/new_tab_page/modules/photos/BUILD.gn
@@ -9,6 +9,5 @@
 mojom("mojo_bindings") {
   sources = [ "photos.mojom" ]
   webui_module_path = "/"
-  use_typescript_sources = true
   public_deps = [ "//url/mojom:url_mojom_gurl" ]
 }
diff --git a/chrome/browser/new_tab_page/modules/recipes/BUILD.gn b/chrome/browser/new_tab_page/modules/recipes/BUILD.gn
index f0b8c91..40aa0579 100644
--- a/chrome/browser/new_tab_page/modules/recipes/BUILD.gn
+++ b/chrome/browser/new_tab_page/modules/recipes/BUILD.gn
@@ -9,6 +9,5 @@
 mojom("mojo_bindings") {
   sources = [ "recipes.mojom" ]
   webui_module_path = "/"
-  use_typescript_sources = true
   public_deps = [ "//url/mojom:url_mojom_gurl" ]
 }
diff --git a/chrome/browser/new_tab_page/modules/v2/history_clusters/BUILD.gn b/chrome/browser/new_tab_page/modules/v2/history_clusters/BUILD.gn
index dce2bf9..1edfb52b 100644
--- a/chrome/browser/new_tab_page/modules/v2/history_clusters/BUILD.gn
+++ b/chrome/browser/new_tab_page/modules/v2/history_clusters/BUILD.gn
@@ -7,7 +7,6 @@
 mojom("mojo_bindings") {
   sources = [ "history_clusters_v2.mojom" ]
   webui_module_path = "/"
-  use_typescript_sources = true
   public_deps = [
     "//chrome/browser/new_tab_page/modules/history_clusters:mojo_bindings",
     "//chrome/browser/new_tab_page/modules/history_clusters/cart:mojo_bindings",
diff --git a/chrome/browser/optimization_guide/model_execution/model_execution_browsertest.cc b/chrome/browser/optimization_guide/model_execution/model_execution_browsertest.cc
new file mode 100644
index 0000000..2e357dd
--- /dev/null
+++ b/chrome/browser/optimization_guide/model_execution/model_execution_browsertest.cc
@@ -0,0 +1,308 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/test.pb.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
+#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/optimization_guide/core/model_execution/model_execution_manager.h"
+#include "components/optimization_guide/core/model_execution/optimization_guide_model_execution_error.h"
+#include "components/optimization_guide/core/optimization_guide_constants.h"
+#include "components/optimization_guide/core/optimization_guide_features.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/dns/mock_host_resolver.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace optimization_guide {
+
+using base::test::TestMessage;
+
+namespace {
+
+enum class ModelExecutionRemoteResponseType {
+  kSuccessful = 0,
+  kUnsuccessful = 1,
+  kMalformed = 2,
+};
+
+TestMessage BuildTestMessage(const std::string& test_message_str) {
+  TestMessage test_message;
+  test_message.set_test(test_message_str);
+  return test_message;
+}
+
+proto::ExecuteResponse BuildTestExecuteResponse(const TestMessage& message) {
+  proto::ExecuteResponse execute_response;
+  proto::Any* any_metadata = execute_response.mutable_response_metadata();
+  any_metadata->set_type_url("type.googleapis.com/" + message.GetTypeName());
+  message.SerializeToString(any_metadata->mutable_value());
+  return execute_response;
+}
+
+}  // namespace
+
+class ModelExecutionBrowserTestBase : public InProcessBrowserTest {
+ public:
+  ModelExecutionBrowserTestBase() = default;
+  ~ModelExecutionBrowserTestBase() override = default;
+
+  ModelExecutionBrowserTestBase(const ModelExecutionBrowserTestBase&) = delete;
+  ModelExecutionBrowserTestBase& operator=(
+      const ModelExecutionBrowserTestBase&) = delete;
+
+  void SetUp() override {
+    InitializeFeatureList();
+    model_execution_server_ = std::make_unique<net::EmbeddedTestServer>(
+        net::EmbeddedTestServer::TYPE_HTTPS);
+    net::EmbeddedTestServer::ServerCertificateConfig cert_config;
+    cert_config.dns_names = {
+        GURL(kOptimizationGuideServiceModelExecutionDefaultURL).host()};
+    model_execution_server_->SetSSLConfig(cert_config);
+    model_execution_server_->RegisterRequestHandler(base::BindRepeating(
+        &ModelExecutionBrowserTestBase::HandleGetModelExecutionRequest,
+        base::Unretained(this)));
+    ASSERT_TRUE(model_execution_server_->Start());
+    InProcessBrowserTest::SetUp();
+  }
+
+  void SetUpOnMainThread() override {
+    InProcessBrowserTest::SetUpOnMainThread();
+    identity_test_env_adaptor_ =
+        std::make_unique<IdentityTestEnvironmentProfileAdaptor>(
+            browser()->profile());
+    host_resolver()->AddRule("*", "127.0.0.1");
+  }
+
+  void SetUpInProcessBrowserTestFixture() override {
+    create_services_subscription_ =
+        BrowserContextDependencyManager::GetInstance()
+            ->RegisterCreateServicesCallbackForTesting(
+                base::BindRepeating(&ModelExecutionBrowserTestBase::
+                                        OnWillCreateBrowserContextServices,
+                                    base::Unretained(this)));
+  }
+
+  void SetUpCommandLine(base::CommandLine* cmd) override {
+    cmd->AppendSwitchASCII(
+        switches::kOptimizationGuideServiceModelExecutionURL,
+        model_execution_server_
+            ->GetURL(
+                GURL(kOptimizationGuideServiceModelExecutionDefaultURL).host(),
+                "/")
+            .spec());
+  }
+
+  void TearDownOnMainThread() override {
+    EXPECT_TRUE(model_execution_server_->ShutdownAndWaitUntilComplete());
+    InProcessBrowserTest::TearDownOnMainThread();
+  }
+
+  void EnableSignin() {
+    identity_test_env_adaptor_->identity_test_env()
+        ->MakePrimaryAccountAvailable("user@gmail.com",
+                                      signin::ConsentLevel::kSignin);
+    identity_test_env_adaptor_->identity_test_env()
+        ->SetAutomaticIssueOfAccessTokens(true);
+  }
+
+  // Executes the model for the feature, waits until the response is received,
+  // and returns the response.
+  void ExecuteModel(proto::ModelExecutionFeature feature,
+                    const TestMessage& request_metadata,
+                    Profile* profile = nullptr) {
+    if (!profile) {
+      profile = browser()->profile();
+    }
+    base::RunLoop run_loop;
+    OptimizationGuideKeyedService* optimization_guide_keyed_service =
+        OptimizationGuideKeyedServiceFactory::GetForProfile(profile);
+    optimization_guide_keyed_service->ExecuteModel(
+        feature, request_metadata,
+        base::BindOnce(&ModelExecutionBrowserTestBase::OnModelExecutionResponse,
+                       base::Unretained(this), run_loop.QuitClosure()));
+    run_loop.Run();
+  }
+
+  void SetExpectedBearerAccessToken(
+      const std::string& expected_bearer_access_token) {
+    expected_bearer_access_token_ = expected_bearer_access_token;
+  }
+
+  void SetResponseType(ModelExecutionRemoteResponseType response_type) {
+    response_type_ = response_type;
+  }
+
+ protected:
+  void OnModelExecutionResponse(
+      base::OnceClosure on_model_execution_closure,
+      OptimizationGuideModelExecutionResult result,
+      std::unique_ptr<ModelQualityLogEntry> log_entry) {
+    if (result.has_value()) {
+      model_execution_result_ = base::ok(result.value());
+    } else {
+      model_execution_result_ = base::unexpected(result.error());
+    }
+    std::move(on_model_execution_closure).Run();
+  }
+
+  std::unique_ptr<net::test_server::HttpResponse>
+  HandleGetModelExecutionRequest(const net::test_server::HttpRequest& request) {
+    auto response = std::make_unique<net::test_server::BasicHttpResponse>();
+    // If the request is a GET, it corresponds to a navigation so return a
+    // normal response.
+    EXPECT_EQ(request.method, net::test_server::METHOD_POST);
+    EXPECT_NE(request.headers.end(), request.headers.find("X-Client-Data"));
+
+    // Access token should be set.
+    EXPECT_TRUE(base::Contains(request.headers,
+                               net::HttpRequestHeaders::kAuthorization));
+    EXPECT_EQ(expected_bearer_access_token_,
+              request.headers.at(net::HttpRequestHeaders::kAuthorization));
+
+    if (response_type_ == ModelExecutionRemoteResponseType::kSuccessful) {
+      std::string serialized_response;
+      proto::ExecuteResponse execute_response =
+          BuildTestExecuteResponse(BuildTestMessage("foo response"));
+      execute_response.SerializeToString(&serialized_response);
+      response->set_code(net::HTTP_OK);
+      response->set_content(serialized_response);
+    } else if (response_type_ ==
+               ModelExecutionRemoteResponseType::kUnsuccessful) {
+      response->set_code(net::HTTP_NOT_FOUND);
+    } else if (response_type_ == ModelExecutionRemoteResponseType::kMalformed) {
+      response->set_code(net::HTTP_OK);
+      response->set_content("Not a proto");
+    } else {
+      NOTREACHED();
+    }
+
+    return std::move(response);
+  }
+
+  void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
+    IdentityTestEnvironmentProfileAdaptor::
+        SetIdentityTestEnvironmentFactoriesOnBrowserContext(context);
+  }
+
+  // Virtualize for testing different feature configurations.
+  virtual void InitializeFeatureList() {}
+
+  base::test::ScopedFeatureList scoped_feature_list_;
+  std::unique_ptr<net::EmbeddedTestServer> model_execution_server_;
+  base::HistogramTester histogram_tester_;
+
+  ModelExecutionRemoteResponseType response_type_ =
+      ModelExecutionRemoteResponseType::kSuccessful;
+
+  // The last model execution response received.
+  absl::optional<OptimizationGuideModelExecutionResult> model_execution_result_;
+
+  // Identity test support.
+  std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
+      identity_test_env_adaptor_;
+  base::CallbackListSubscription create_services_subscription_;
+
+  // The expected authorization header holding the bearer access token.
+  std::string expected_bearer_access_token_;
+};
+
+class ModelExecutionDisabledBrowserTest : public ModelExecutionBrowserTestBase {
+  void InitializeFeatureList() override {
+    scoped_feature_list_.InitAndDisableFeature(
+        features::kOptimizationGuideModelExecution);
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(ModelExecutionDisabledBrowserTest,
+                       ModelExecutionDisabled) {
+  ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, BuildTestMessage("foo"));
+  EXPECT_TRUE(model_execution_result_.has_value());
+  EXPECT_FALSE(model_execution_result_->has_value());
+  EXPECT_EQ(OptimizationGuideModelExecutionError::ModelExecutionError::
+                kGenericFailure,
+            model_execution_result_->error().error());
+  EXPECT_TRUE(model_execution_result_->error().transient());
+}
+
+class ModelExecutionEnabledBrowserTest : public ModelExecutionBrowserTestBase {
+  void InitializeFeatureList() override {
+    scoped_feature_list_.InitAndEnableFeature(
+        features::kOptimizationGuideModelExecution);
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
+                       ModelExecutionDisabledInIncognito) {
+  Browser* otr_browser = CreateIncognitoBrowser(browser()->profile());
+  ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, BuildTestMessage("foo"),
+               otr_browser->profile());
+  EXPECT_TRUE(model_execution_result_.has_value());
+  EXPECT_FALSE(model_execution_result_->has_value());
+  EXPECT_EQ(OptimizationGuideModelExecutionError::ModelExecutionError::
+                kGenericFailure,
+            model_execution_result_->error().error());
+  EXPECT_TRUE(model_execution_result_->error().transient());
+}
+
+IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
+                       ModelExecutionFailsNoUserSignIn) {
+  ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, BuildTestMessage("foo"));
+  EXPECT_TRUE(model_execution_result_.has_value());
+  EXPECT_FALSE(model_execution_result_->has_value());
+  EXPECT_EQ(OptimizationGuideModelExecutionError::ModelExecutionError::
+                kPermissionDenied,
+            model_execution_result_->error().error());
+  EXPECT_FALSE(model_execution_result_->error().transient());
+}
+
+IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
+                       ModelExecutionSuccess) {
+  EnableSignin();
+  SetExpectedBearerAccessToken("Bearer access_token");
+
+  ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, BuildTestMessage("foo"));
+  EXPECT_TRUE(model_execution_result_.has_value());
+  EXPECT_TRUE(model_execution_result_->has_value());
+  EXPECT_EQ(
+      "foo response",
+      ParsedAnyMetadata<TestMessage>(model_execution_result_->value())->test());
+}
+
+IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
+                       ModelExecutionFailsForUnsuccessfulResponse) {
+  EnableSignin();
+  SetExpectedBearerAccessToken("Bearer access_token");
+  SetResponseType(ModelExecutionRemoteResponseType::kUnsuccessful);
+
+  ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, BuildTestMessage("foo"));
+  EXPECT_TRUE(model_execution_result_.has_value());
+  EXPECT_FALSE(model_execution_result_->has_value());
+  EXPECT_EQ(OptimizationGuideModelExecutionError::ModelExecutionError::
+                kGenericFailure,
+            model_execution_result_->error().error());
+  EXPECT_TRUE(model_execution_result_->error().transient());
+}
+
+IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
+                       ModelExecutionFailsForMalformedResponse) {
+  EnableSignin();
+  SetExpectedBearerAccessToken("Bearer access_token");
+  SetResponseType(ModelExecutionRemoteResponseType::kMalformed);
+
+  ExecuteModel(proto::MODEL_EXECUTION_FEATURE_COMPOSE, BuildTestMessage("foo"));
+  EXPECT_TRUE(model_execution_result_.has_value());
+  EXPECT_FALSE(model_execution_result_->has_value());
+  EXPECT_EQ(OptimizationGuideModelExecutionError::ModelExecutionError::
+                kGenericFailure,
+            model_execution_result_->error().error());
+  EXPECT_TRUE(model_execution_result_->error().transient());
+}
+
+}  // namespace optimization_guide
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 52c6dbb..2d9ff7e 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -82,6 +82,7 @@
 #include "extensions/browser/api/file_system/file_system_api.h"
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/app_window/app_window_registry.h"
+#include "extensions/browser/extension_web_contents_observer.h"
 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.h"
 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
 #include "extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h"
@@ -3130,3 +3131,38 @@
   // run (the task should be canceled/ignored), so wait for this to happen.
   base::RunLoop().RunUntilIdle();
 }
+
+// Ensure that extensions do not get multiple bound LocalMainFrames for guest
+// views. This is a regression test for crbug.com/1367582.
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, ExtensionsBindingLocalHost) {
+  // Load test PDF in first tab.
+  const GURL main_url(embedded_test_server()->GetURL("/pdf/test.pdf"));
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  auto* primary_main_frame = GetActiveWebContents()->GetPrimaryMainFrame();
+
+  // Verify the PDF has loaded.
+  auto* guest_view = GetGuestViewManager()->WaitForSingleGuestViewCreated();
+  ASSERT_TRUE(guest_view);
+  EXPECT_NE(primary_main_frame, guest_view->GetGuestMainFrame());
+
+  auto* web_contents_observer =
+      extensions::ExtensionWebContentsObserver::GetForWebContents(
+          GetActiveWebContents());
+  primary_main_frame->ForEachRenderFrameHost(
+      [web_contents_observer](content::RenderFrameHost* frame_host) {
+        web_contents_observer->GetLocalFrame(frame_host);
+      });
+  auto* guest_view_web_contents_observer =
+      extensions::ExtensionWebContentsObserver::GetForWebContents(
+          guest_view->web_contents());
+  guest_view->GetGuestMainFrame()->ForEachRenderFrameHost(
+      [guest_view_web_contents_observer](content::RenderFrameHost* frame_host) {
+        guest_view_web_contents_observer->GetLocalFrame(frame_host);
+      });
+
+  // Execute some script in each of the frames to ensure the above bindings
+  // have been executed in the renderer. They would previously have caused
+  // a process crash.
+  EXPECT_EQ(1, content::EvalJs(primary_main_frame, "1;").ExtractInt());
+  EXPECT_EQ(1, content::EvalJs(guest_view->web_contents(), "1;").ExtractInt());
+}
diff --git a/chrome/browser/performance_manager/metrics/metrics_provider_desktop.cc b/chrome/browser/performance_manager/metrics/metrics_provider_desktop.cc
index ec30461e..ac4324ef 100644
--- a/chrome/browser/performance_manager/metrics/metrics_provider_desktop.cc
+++ b/chrome/browser/performance_manager/metrics/metrics_provider_desktop.cc
@@ -179,7 +179,7 @@
                           base::Unretained(this)));
 }
 
-void MetricsProviderDesktop::OnBatterySaverModeChanged(bool is_active) {
+void MetricsProviderDesktop::OnBatterySaverActiveChanged(bool is_active) {
   battery_saver_enabled_ = is_active;
   battery_saver_mode_tracker_->ModeChanged(battery_saver_enabled_);
   OnTuningModesChanged();
diff --git a/chrome/browser/performance_manager/metrics/metrics_provider_desktop.h b/chrome/browser/performance_manager/metrics/metrics_provider_desktop.h
index ba8668c..850bbc3 100644
--- a/chrome/browser/performance_manager/metrics/metrics_provider_desktop.h
+++ b/chrome/browser/performance_manager/metrics/metrics_provider_desktop.h
@@ -58,7 +58,7 @@
   explicit MetricsProviderDesktop(PrefService* local_state);
 
   // BatterySaverModeManager::Observer:
-  void OnBatterySaverModeChanged(bool is_active) override;
+  void OnBatterySaverActiveChanged(bool is_active) override;
 
   void OnHighEfficiencyPrefChanged();
   void OnTuningModesChanged();
diff --git a/chrome/browser/performance_manager/metrics/page_timeline_monitor.cc b/chrome/browser/performance_manager/metrics/page_timeline_monitor.cc
index c634780e..8437319 100644
--- a/chrome/browser/performance_manager/metrics/page_timeline_monitor.cc
+++ b/chrome/browser/performance_manager/metrics/page_timeline_monitor.cc
@@ -355,40 +355,46 @@
   }
   CHECK(suffix);
 
+  const int total_background_cpu_percent =
+      total_background_cpu_usage * 100 / base::SysInfo::NumberOfProcessors();
   base::UmaHistogramPercentage(
       base::StrCat({"PerformanceManager.PerformanceInterventions.CPU."
                     "TotalBackgroundCPU.",
                     suffix}),
-      total_background_cpu_usage * 100 / base::SysInfo::NumberOfProcessors());
+      total_background_cpu_percent);
   base::UmaHistogramCounts1000(
       base::StrCat({"PerformanceManager.PerformanceInterventions.CPU."
                     "TotalBackgroundTabCount.",
                     suffix}),
       background_tab_count);
-  base::UmaHistogramPercentage(
-      base::StrCat({"PerformanceManager.PerformanceInterventions.CPU."
-                    "AverageBackgroundCPU.",
-                    suffix}),
-      total_background_cpu_usage * 100 / base::SysInfo::NumberOfProcessors() /
-          background_tab_count);
+  if (background_tab_count) {
+    base::UmaHistogramPercentage(
+        base::StrCat({"PerformanceManager.PerformanceInterventions.CPU."
+                      "AverageBackgroundCPU.",
+                      suffix}),
+        total_background_cpu_percent / background_tab_count);
+  }
 
   // Log basic foreground UMA metrics.
+  const int total_foreground_cpu_percent =
+      total_foreground_cpu_usage * 100 / base::SysInfo::NumberOfProcessors();
   base::UmaHistogramPercentage(
       base::StrCat({"PerformanceManager.PerformanceInterventions.CPU."
                     "TotalForegroundCPU.",
                     suffix}),
-      total_foreground_cpu_usage * 100 / base::SysInfo::NumberOfProcessors());
+      total_foreground_cpu_percent);
   base::UmaHistogramCounts1000(
       base::StrCat({"PerformanceManager.PerformanceInterventions.CPU."
                     "TotalForegroundTabCount.",
                     suffix}),
       foreground_tab_count);
-  base::UmaHistogramPercentage(
-      base::StrCat({"PerformanceManager.PerformanceInterventions.CPU."
-                    "AverageForegroundCPU.",
-                    suffix}),
-      total_foreground_cpu_usage * 100 / base::SysInfo::NumberOfProcessors() /
-          foreground_tab_count);
+  if (foreground_tab_count) {
+    base::UmaHistogramPercentage(
+        base::StrCat({"PerformanceManager.PerformanceInterventions.CPU."
+                      "AverageForegroundCPU.",
+                      suffix}),
+        total_foreground_cpu_percent / foreground_tab_count);
+  }
 
   // Log derived background UMA metrics.
   if (histogram_suffix == CPUInterventionSuffix::kBaseline) {
diff --git a/chrome/browser/performance_manager/metrics/page_timeline_monitor_unittest.cc b/chrome/browser/performance_manager/metrics/page_timeline_monitor_unittest.cc
index fff7dab..c9eb107 100644
--- a/chrome/browser/performance_manager/metrics/page_timeline_monitor_unittest.cc
+++ b/chrome/browser/performance_manager/metrics/page_timeline_monitor_unittest.cc
@@ -931,6 +931,73 @@
   ExpectNoCPUHistogram("TopNBackgroundCPU.1", "Delayed");
   ExpectNoCPUHistogram("TopNBackgroundCPU.2", "Delayed");
 }
+
+TEST_P(PageTimelineMonitorWithFeatureTest,
+       TestCPUInterventionMetricsNoForegroundTabs) {
+  MockSinglePageInSingleProcessGraph mock_graph(graph());
+  mock_graph.page->SetType(performance_manager::PageType::kTab);
+  cpu_delegate_factory_.GetDelegate(mock_graph.process.get())
+      .SetCPUUsage(base::SysInfo::NumberOfProcessors());
+
+  // Put the only tab in the background.
+  mock_graph.page->SetIsVisible(false);
+
+  // Let an arbitrary amount of time pass so there's some CPU usage to measure.
+  task_env().FastForwardBy(base::Minutes(1));
+  TriggerCollectPageResourceUsage();
+
+  ExpectCPUHistogram("AverageBackgroundCPU", "Baseline", 100);
+  ExpectCPUHistogram("TotalBackgroundCPU", "Baseline", 100);
+  ExpectCPUHistogram("TotalBackgroundTabCount", "Baseline", 1);
+  // AverageForegroundCPU would divide by 0.
+  ExpectCPUHistogram("TotalForegroundCPU", "Baseline", 0);
+  ExpectCPUHistogram("TotalForegroundTabCount", "Baseline", 0);
+
+  ExpectCPUHistogram("AverageBackgroundCPU", "Immediate", 100);
+  ExpectCPUHistogram("TotalBackgroundCPU", "Immediate", 100);
+  ExpectCPUHistogram("TotalBackgroundTabCount", "Immediate", 1);
+  // AverageForegroundCPU would divide by 0.
+  ExpectCPUHistogram("TotalForegroundCPU", "Immediate", 0);
+  ExpectCPUHistogram("TotalForegroundTabCount", "Immediate", 0);
+  ExpectCPUHistogram("BackgroundTabsToGetUnderCPUThreshold", "Immediate", 1);
+  ExpectCPUHistogram("TopNBackgroundCPU.1", "Immediate", 100);
+  ExpectCPUHistogram("TopNBackgroundCPU.2", "Immediate", 100);
+}
+
+TEST_P(PageTimelineMonitorWithFeatureTest,
+       TestCPUInterventionMetricsNoBackgroundTabs) {
+  MockSinglePageInSingleProcessGraph mock_graph(graph());
+  mock_graph.page->SetType(performance_manager::PageType::kTab);
+  cpu_delegate_factory_.GetDelegate(mock_graph.process.get())
+      .SetCPUUsage(base::SysInfo::NumberOfProcessors());
+
+  // Put the only tab in the foreground.
+  mock_graph.page->SetIsVisible(true);
+
+  // Let an arbitrary amount of time pass so there's some CPU usage to measure.
+  task_env().FastForwardBy(base::Minutes(1));
+  TriggerCollectPageResourceUsage();
+
+  // AverageBackgroundCPU would divide by 0.
+  ExpectCPUHistogram("TotalBackgroundCPU", "Baseline", 0);
+  ExpectCPUHistogram("TotalBackgroundTabCount", "Baseline", 0);
+  ExpectCPUHistogram("AverageForegroundCPU", "Baseline", 100);
+  ExpectCPUHistogram("TotalForegroundCPU", "Baseline", 100);
+  ExpectCPUHistogram("TotalForegroundTabCount", "Baseline", 1);
+
+  // AverageBackgroundCPU would divide by 0.
+  ExpectCPUHistogram("TotalBackgroundCPU", "Immediate", 0);
+  ExpectCPUHistogram("TotalBackgroundTabCount", "Immediate", 0);
+  ExpectCPUHistogram("AverageForegroundCPU", "Immediate", 100);
+  ExpectCPUHistogram("TotalForegroundCPU", "Immediate", 100);
+  ExpectCPUHistogram("TotalForegroundTabCount", "Immediate", 1);
+  // BackgroundTabsToGetUnderCPUThreshold is basically infinite (goes in the
+  // overflow bucket.)
+  ExpectCPUHistogram("BackgroundTabsToGetUnderCPUThreshold", "Immediate", 9999);
+  ExpectCPUHistogram("TopNBackgroundCPU.1", "Immediate", 0);
+  ExpectCPUHistogram("TopNBackgroundCPU.2", "Immediate", 0);
+}
+
 #endif
 
 }  // namespace performance_manager::metrics
diff --git a/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc b/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc
index 44f6019..ef195cd 100644
--- a/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc
+++ b/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc
@@ -104,9 +104,9 @@
   other_frame_node->SetIsCurrent(true);
 
   // frame_node() is created with a URL. `other_frame_node` starts without.
-  ASSERT_FALSE(frame_node()->url().is_empty());
+  ASSERT_FALSE(frame_node()->GetURL().is_empty());
   ASSERT_TRUE(frame_node()->is_current());
-  ASSERT_TRUE(other_frame_node->url().is_empty());
+  ASSERT_TRUE(other_frame_node->GetURL().is_empty());
   ASSERT_TRUE(other_frame_node->is_current());
 
   // An arbitrary "current" frame will be returned by GetMainFrameNode(). Make
@@ -118,9 +118,9 @@
 
   SetPageAndFrameUrl(GURL(), page_node(), frame_node());
 
-  ASSERT_TRUE(frame_node()->url().is_empty());
+  ASSERT_TRUE(frame_node()->GetURL().is_empty());
   ASSERT_TRUE(frame_node()->is_current());
-  ASSERT_TRUE(other_frame_node->url().is_empty());
+  ASSERT_TRUE(other_frame_node->GetURL().is_empty());
   ASSERT_TRUE(other_frame_node->is_current());
 
   EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT));
@@ -130,9 +130,9 @@
   SetPageAndFrameUrl(GURL("https://foo.com"), page_node(),
                      other_frame_node.get());
 
-  ASSERT_TRUE(frame_node()->url().is_empty());
+  ASSERT_TRUE(frame_node()->GetURL().is_empty());
   ASSERT_TRUE(frame_node()->is_current());
-  ASSERT_FALSE(other_frame_node->url().is_empty());
+  ASSERT_FALSE(other_frame_node->GetURL().is_empty());
   ASSERT_TRUE(other_frame_node->is_current());
 
   EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::URGENT));
diff --git a/chrome/browser/performance_manager/policies/page_freezing_policy_unittest.cc b/chrome/browser/performance_manager/policies/page_freezing_policy_unittest.cc
index 1ed0633..cb750e0c 100644
--- a/chrome/browser/performance_manager/policies/page_freezing_policy_unittest.cc
+++ b/chrome/browser/performance_manager/policies/page_freezing_policy_unittest.cc
@@ -101,42 +101,42 @@
 
 TEST_F(PageFreezingPolicyTest, AudiblePageGetsCannotFreezeVote) {
   page_node()->SetIsAudible(true);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCannotFreeze);
-  EXPECT_EQ(page_node()->freezing_vote()->reason(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->reason(),
             PageFreezingPolicyAccess::CannotFreezeReasonToString(
                 PageFreezingPolicyAccess::CannotFreezeReason::kAudible));
 }
 
 TEST_F(PageFreezingPolicyTest, RecentlyAudiblePageGetsCannotFreezeVote) {
   page_node()->SetIsAudible(true);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCannotFreeze);
   task_env().FastForwardBy(base::Seconds(1));
   page_node()->SetIsAudible(false);
   EXPECT_EQ(
-      page_node()->freezing_vote()->reason(),
+      page_node()->GetFreezingVote()->reason(),
       PageFreezingPolicyAccess::CannotFreezeReasonToString(
           PageFreezingPolicyAccess::CannotFreezeReason::kRecentlyAudible));
   task_env().FastForwardBy(policies::kTabAudioProtectionTime);
-  EXPECT_FALSE(page_node()->freezing_vote().has_value());
+  EXPECT_FALSE(page_node()->GetFreezingVote().has_value());
 }
 
 TEST_F(PageFreezingPolicyTest, PageHoldingWeblockGetsCannotFreezeVote) {
   page_node()->SetIsHoldingWebLockForTesting(true);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCannotFreeze);
-  EXPECT_EQ(page_node()->freezing_vote()->reason(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->reason(),
             PageFreezingPolicyAccess::CannotFreezeReasonToString(
                 PageFreezingPolicyAccess::CannotFreezeReason::kHoldingWebLock));
 }
 
 TEST_F(PageFreezingPolicyTest, PageHoldingIndexedDBLockGetsCannotFreezeVote) {
   page_node()->SetIsHoldingIndexedDBLockForTesting(true);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCannotFreeze);
   EXPECT_EQ(
-      page_node()->freezing_vote()->reason(),
+      page_node()->GetFreezingVote()->reason(),
       PageFreezingPolicyAccess::CannotFreezeReasonToString(
           PageFreezingPolicyAccess::CannotFreezeReason::kHoldingIndexedDBLock));
 }
@@ -144,10 +144,10 @@
 TEST_F(PageFreezingPolicyTest, CannotFreezeIsConnectedToUSBDevice) {
   PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node())
       ->SetIsConnectedToUSBDeviceForTesting(true);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCannotFreeze);
   EXPECT_EQ(
-      page_node()->freezing_vote()->reason(),
+      page_node()->GetFreezingVote()->reason(),
       PageFreezingPolicyAccess::CannotFreezeReasonToString(
           PageFreezingPolicyAccess::CannotFreezeReason::kConnectedToUsbDevice));
 }
@@ -155,9 +155,9 @@
 TEST_F(PageFreezingPolicyTest, CannotFreezePageConnectedToBluetoothDevice) {
   PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node())
       ->SetIsConnectedToBluetoothDeviceForTesting(true);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCannotFreeze);
-  EXPECT_EQ(page_node()->freezing_vote()->reason(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->reason(),
             PageFreezingPolicyAccess::CannotFreezeReasonToString(
                 PageFreezingPolicyAccess::CannotFreezeReason::
                     kConnectedToBluetoothDevice));
@@ -166,9 +166,9 @@
 TEST_F(PageFreezingPolicyTest, CannotFreezePageCapturingVideo) {
   PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node())
       ->SetIsCapturingVideoForTesting(true);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCannotFreeze);
-  EXPECT_EQ(page_node()->freezing_vote()->reason(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->reason(),
             PageFreezingPolicyAccess::CannotFreezeReasonToString(
                 PageFreezingPolicyAccess::CannotFreezeReason::kCapturingVideo));
 }
@@ -176,9 +176,9 @@
 TEST_F(PageFreezingPolicyTest, CannotFreezePageCapturingAudio) {
   PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node())
       ->SetIsCapturingAudioForTesting(true);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCannotFreeze);
-  EXPECT_EQ(page_node()->freezing_vote()->reason(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->reason(),
             PageFreezingPolicyAccess::CannotFreezeReasonToString(
                 PageFreezingPolicyAccess::CannotFreezeReason::kCapturingAudio));
 }
@@ -186,9 +186,9 @@
 TEST_F(PageFreezingPolicyTest, CannotFreezePageBeingMirrored) {
   PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node())
       ->SetIsBeingMirroredForTesting(true);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCannotFreeze);
-  EXPECT_EQ(page_node()->freezing_vote()->reason(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->reason(),
             PageFreezingPolicyAccess::CannotFreezeReasonToString(
                 PageFreezingPolicyAccess::CannotFreezeReason::kBeingMirrored));
 }
@@ -196,17 +196,17 @@
 TEST_F(PageFreezingPolicyTest, CannotFreezePageCapturingWindow) {
   PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node())
       ->SetIsCapturingWindowForTesting(true);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCannotFreeze);
 }
 
 TEST_F(PageFreezingPolicyTest, CannotFreezePageCapturingDisplay) {
   PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node())
       ->SetIsCapturingDisplayForTesting(true);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCannotFreeze);
   EXPECT_EQ(
-      page_node()->freezing_vote()->reason(),
+      page_node()->GetFreezingVote()->reason(),
       PageFreezingPolicyAccess::CannotFreezeReasonToString(
           PageFreezingPolicyAccess::CannotFreezeReason::kCapturingDisplay));
 }
@@ -254,7 +254,7 @@
   // The page freezer shouldn't be called as the page node isn't fully loaded
   // yet.
   ::testing::Mock::VerifyAndClearExpectations(page_freezer_raw);
-  EXPECT_EQ(page_node()->freezing_vote()->value(),
+  EXPECT_EQ(page_node()->GetFreezingVote()->value(),
             freezing::FreezingVoteValue::kCanFreeze);
 
   EXPECT_CALL(*page_freezer_raw, MaybeFreezePageNodeImpl(page_node()));
diff --git a/chrome/browser/performance_manager/public/user_tuning/battery_saver_mode_manager.h b/chrome/browser/performance_manager/public/user_tuning/battery_saver_mode_manager.h
index 7af8e11..c89a84a 100644
--- a/chrome/browser/performance_manager/public/user_tuning/battery_saver_mode_manager.h
+++ b/chrome/browser/performance_manager/public/user_tuning/battery_saver_mode_manager.h
@@ -49,16 +49,21 @@
 
   class Observer : public base::CheckedObserver {
    public:
+    // Raised when the browser level battery saver mode is enabled or disabled.
+    // Both `kEnabledOnBattery` and `kEnabledBelowThreshold` are considered
+    // enabled. This does not imply whether the mode is active or not.
+    virtual void OnBatterySaverModeChanged(bool is_enabled) {}
+
     // Raised when the battery saver mode interventions are activated or
     // deactivated
-    virtual void OnBatterySaverModeChanged(bool is_active) {}
+    virtual void OnBatterySaverActiveChanged(bool is_active) {}
 
     // Raised when the device is plugged in or unplugged
     // Can be used by the UI to show a promo if BSM isn't configured to be
     // enabled when on battery power.
     // If the connection/disconnection from power causes battery saver to be
     // enabled/disabled, the state of battery saver will not yet be updated when
-    // this is invoked. `OnBatterySaverModeChanged` will be invoked after the
+    // this is invoked. `OnBatterySaverActiveChanged` will be invoked after the
     // state is updated.
     virtual void OnExternalPowerConnectedChanged(bool on_battery_power) {}
 
@@ -93,6 +98,18 @@
   // sampled for the first time.
   bool DeviceHasBattery() const;
 
+  // Returns true if Battery Saver Mode is enabled for the user. If any state
+  // transitions cause an observer notification, this is guaranteed to reflect
+  // the *new* value when the observers are notified so the UI layer can make
+  // decisions based on the most up-to-date state.
+  bool IsBatterySaverModeEnabled();
+
+  // Returns true if Battery Saver Mode is a managed pref. If any state
+  // transitions cause an observer notification, this is guaranteed to reflect
+  // the *new* value when the observers are notified so the UI layer can make
+  // decisions based on the most up-to-date state.
+  bool IsBatterySaverModeManaged() const;
+
   // Returns true if Battery Saver Mode interventions are active. If any state
   // transitions cause an observer notification, this is guaranteed to reflect
   // the *new* value when the observers are notified so the UI layer can make
@@ -128,6 +145,8 @@
     virtual ~BatterySaverProvider() = default;
 
     virtual bool DeviceHasBattery() const = 0;
+    virtual bool IsBatterySaverModeEnabled() = 0;
+    virtual bool IsBatterySaverModeManaged() = 0;
     virtual bool IsBatterySaverActive() const = 0;
     virtual bool IsUsingBatteryPower() const = 0;
     virtual base::Time GetLastBatteryUsageTimestamp() const = 0;
@@ -145,6 +164,7 @@
   // Called from the installed BatterySaverProvider to signify a change in
   // battery saver mode related state.
   void NotifyOnBatterySaverModeChanged(bool battery_saver_mode_enabled);
+  void NotifyOnBatterySaverActiveChanged(bool battery_saver_mode_active);
   void NotifyOnExternalPowerConnectedChanged(bool on_battery_power);
   void NotifyOnDeviceHasBatteryChanged(bool has_battery);
   void NotifyOnBatteryThresholdReached();
diff --git a/chrome/browser/performance_manager/user_tuning/battery_saver_mode_manager.cc b/chrome/browser/performance_manager/user_tuning/battery_saver_mode_manager.cc
index 9462820e..befdb27 100644
--- a/chrome/browser/performance_manager/user_tuning/battery_saver_mode_manager.cc
+++ b/chrome/browser/performance_manager/user_tuning/battery_saver_mode_manager.cc
@@ -36,6 +36,9 @@
 
 constexpr base::TimeDelta kBatteryUsageWriteFrequency = base::Days(1);
 
+using BatterySaverModeState =
+    performance_manager::user_tuning::prefs::BatterySaverModeState;
+
 // On certain platforms (ChromeOS), the battery level displayed to the user is
 // artificially lower than the actual battery level. Unfortunately, the battery
 // level that Battery Saver Mode looks at is the "actual" level, so users on
@@ -126,7 +129,7 @@
       battery_state_sampler_obs_.Observe(battery_state_sampler);
     }
 
-    OnBatterySaverModePrefChanged();
+    UpdateBatterySaverModeState();
   }
 
   ~DesktopBatterySaverProvider() override {
@@ -135,6 +138,16 @@
 
   // BatterySaverProvider:
   bool DeviceHasBattery() const override { return has_battery_; }
+  bool IsBatterySaverModeEnabled() override {
+    BatterySaverModeState state = performance_manager::user_tuning::prefs::
+        GetCurrentBatterySaverModeState(pref_change_registrar_.prefs());
+    return state != BatterySaverModeState::kDisabled;
+  }
+  bool IsBatterySaverModeManaged() override {
+    auto* pref = pref_change_registrar_.prefs()->FindPreference(
+        prefs::kBatterySaverModeState);
+    return pref->IsManaged();
+  }
   bool IsBatterySaverActive() const override {
     return battery_saver_mode_enabled_;
   }
@@ -162,11 +175,14 @@
   void OnBatterySaverModePrefChanged() {
     battery_saver_mode_disabled_for_session_ = false;
     UpdateBatterySaverModeState();
+    manager_->NotifyOnBatterySaverModeChanged(
+        performance_manager::user_tuning::prefs::
+            GetCurrentBatterySaverModeState(pref_change_registrar_.prefs()) !=
+        performance_manager::user_tuning::prefs::BatterySaverModeState::
+            kDisabled);
   }
 
   void UpdateBatterySaverModeState() {
-    using BatterySaverModeState =
-        performance_manager::user_tuning::prefs::BatterySaverModeState;
     BatterySaverModeState state = performance_manager::user_tuning::prefs::
         GetCurrentBatterySaverModeState(pref_change_registrar_.prefs());
 
@@ -197,7 +213,7 @@
       return;
     }
 
-    manager_->NotifyOnBatterySaverModeChanged(battery_saver_mode_enabled_);
+    manager_->NotifyOnBatterySaverActiveChanged(battery_saver_mode_enabled_);
   }
 
   // base::PowerStateObserver:
@@ -337,7 +353,7 @@
 
     enabled_ = state.enabled();
 
-    manager_->NotifyOnBatterySaverModeChanged(enabled_);
+    manager_->NotifyOnBatterySaverActiveChanged(enabled_);
   }
 
   void PowerChanged(
@@ -350,6 +366,8 @@
 
   // BatterySaverProvider:
   bool DeviceHasBattery() const override { return has_battery_; }
+  bool IsBatterySaverModeEnabled() override { return false; }
+  bool IsBatterySaverModeManaged() override { return false; }
   bool IsBatterySaverActive() const override { return enabled_; }
   bool IsUsingBatteryPower() const override { return false; }
   base::Time GetLastBatteryUsageTimestamp() const override {
@@ -410,6 +428,16 @@
   return battery_saver_provider_ && battery_saver_provider_->DeviceHasBattery();
 }
 
+bool BatterySaverModeManager::IsBatterySaverModeEnabled() {
+  return battery_saver_provider_ &&
+         battery_saver_provider_->IsBatterySaverModeEnabled();
+}
+
+bool BatterySaverModeManager::IsBatterySaverModeManaged() const {
+  return battery_saver_provider_ &&
+         battery_saver_provider_->IsBatterySaverModeManaged();
+}
+
 bool BatterySaverModeManager::IsBatterySaverActive() const {
   return battery_saver_provider_ &&
          battery_saver_provider_->IsBatterySaverActive();
@@ -473,16 +501,24 @@
 
 void BatterySaverModeManager::NotifyOnBatterySaverModeChanged(
     bool battery_saver_mode_enabled) {
-  if (battery_saver_mode_enabled) {
+  for (auto& obs : observers_) {
+    obs.OnBatterySaverModeChanged(battery_saver_mode_enabled);
+  }
+}
+
+void BatterySaverModeManager::NotifyOnBatterySaverActiveChanged(
+    bool battery_saver_mode_active) {
+  if (battery_saver_mode_active) {
     frame_throttling_delegate_->StartThrottlingAllFrameSinks();
   } else {
     frame_throttling_delegate_->StopThrottlingAllFrameSinks();
   }
 
   for (auto& obs : observers_) {
-    obs.OnBatterySaverModeChanged(battery_saver_mode_enabled);
+    obs.OnBatterySaverActiveChanged(battery_saver_mode_active);
   }
 }
+
 void BatterySaverModeManager::NotifyOnExternalPowerConnectedChanged(
     bool on_battery_power) {
   for (auto& obs : observers_) {
diff --git a/chrome/browser/performance_manager/user_tuning/battery_saver_mode_manager_unittest.cc b/chrome/browser/performance_manager/user_tuning/battery_saver_mode_manager_unittest.cc
index 27bad42..ab2afe73 100644
--- a/chrome/browser/performance_manager/user_tuning/battery_saver_mode_manager_unittest.cc
+++ b/chrome/browser/performance_manager/user_tuning/battery_saver_mode_manager_unittest.cc
@@ -58,7 +58,7 @@
   ~QuitRunLoopOnBSMChangeObserver() override = default;
 
   // BatterySaverModeManager::Observer implementation:
-  void OnBatterySaverModeChanged(bool) override { Quit(); }
+  void OnBatterySaverActiveChanged(bool) override { Quit(); }
 };
 
 class QuitRunLoopOnPowerStateChangeObserver : public QuitRunLoopObserverBase {
@@ -172,14 +172,17 @@
       static_cast<int>(performance_manager::user_tuning::prefs::
                            BatterySaverModeState::kEnabled));
 
+  EXPECT_TRUE(manager()->IsBatterySaverModeEnabled());
   EXPECT_TRUE(manager()->IsBatterySaverActive());
   EXPECT_TRUE(throttling_enabled());
 
   manager()->SetTemporaryBatterySaverDisabledForSession(true);
+  EXPECT_TRUE(manager()->IsBatterySaverModeEnabled());
   EXPECT_FALSE(manager()->IsBatterySaverActive());
   EXPECT_FALSE(throttling_enabled());
 
   manager()->SetTemporaryBatterySaverDisabledForSession(false);
+  EXPECT_TRUE(manager()->IsBatterySaverModeEnabled());
   EXPECT_TRUE(manager()->IsBatterySaverActive());
   EXPECT_TRUE(throttling_enabled());
 
@@ -243,6 +246,7 @@
       performance_manager::user_tuning::prefs::kBatterySaverModeState,
       static_cast<int>(performance_manager::user_tuning::prefs::
                            BatterySaverModeState::kEnabled));
+  EXPECT_TRUE(manager()->IsBatterySaverModeEnabled());
   EXPECT_TRUE(manager()->IsBatterySaverActive());
   EXPECT_TRUE(throttling_enabled());
 
@@ -250,6 +254,7 @@
       performance_manager::user_tuning::prefs::kBatterySaverModeState,
       static_cast<int>(performance_manager::user_tuning::prefs::
                            BatterySaverModeState::kDisabled));
+  EXPECT_FALSE(manager()->IsBatterySaverModeEnabled());
   EXPECT_FALSE(manager()->IsBatterySaverActive());
   EXPECT_FALSE(throttling_enabled());
 }
@@ -521,6 +526,7 @@
   manager()->RemoveObserver(observer.get());
 
   EXPECT_TRUE(manager()->IsBatterySaverActive());
+  EXPECT_FALSE(manager()->IsBatterySaverModeEnabled());
   EXPECT_TRUE(throttling_enabled());
 }
 
diff --git a/chrome/browser/printing/browser_printing_context_factory_for_test.cc b/chrome/browser/printing/browser_printing_context_factory_for_test.cc
index 50a7f8c..33291cc 100644
--- a/chrome/browser/printing/browser_printing_context_factory_for_test.cc
+++ b/chrome/browser/printing/browser_printing_context_factory_for_test.cc
@@ -19,10 +19,10 @@
 
 std::unique_ptr<TestPrintingContext> MakeDefaultTestPrintingContext(
     PrintingContext::Delegate* delegate,
-    bool skip_system_calls,
+    PrintingContext::ProcessBehavior process_behavior,
     const std::string& printer_name) {
   auto context =
-      std::make_unique<TestPrintingContext>(delegate, skip_system_calls);
+      std::make_unique<TestPrintingContext>(delegate, process_behavior);
 
   context->SetDeviceSettings(printer_name,
                              test::MakeDefaultPrintSettings(printer_name));
@@ -40,9 +40,9 @@
 std::unique_ptr<PrintingContext>
 BrowserPrintingContextFactoryForTest::CreatePrintingContext(
     PrintingContext::Delegate* delegate,
-    bool skip_system_calls) {
-  auto context = MakeDefaultTestPrintingContext(delegate, skip_system_calls,
-                                                printer_name_);
+    PrintingContext::ProcessBehavior process_behavior) {
+  auto context =
+      MakeDefaultTestPrintingContext(delegate, process_behavior, printer_name_);
 
   if (cancels_in_new_document_) {
     context->SetNewDocumentCancels();
diff --git a/chrome/browser/printing/browser_printing_context_factory_for_test.h b/chrome/browser/printing/browser_printing_context_factory_for_test.h
index c5d10d7..b9a2798 100644
--- a/chrome/browser/printing/browser_printing_context_factory_for_test.h
+++ b/chrome/browser/printing/browser_printing_context_factory_for_test.h
@@ -24,7 +24,7 @@
 
   std::unique_ptr<PrintingContext> CreatePrintingContext(
       PrintingContext::Delegate* delegate,
-      bool skip_system_calls) override;
+      PrintingContext::ProcessBehavior process_behavior) override;
 
   void SetPrinterNameForSubsequentContexts(const std::string& printer_name);
   void SetCancelErrorOnNewDocument(bool cause_errors);
diff --git a/chrome/browser/printing/print_backend_browsertest.cc b/chrome/browser/printing/print_backend_browsertest.cc
index 5c4f95b..479631f 100644
--- a/chrome/browser/printing/print_backend_browsertest.cc
+++ b/chrome/browser/printing/print_backend_browsertest.cc
@@ -400,9 +400,9 @@
    public:
     std::unique_ptr<PrintingContext> CreatePrintingContext(
         PrintingContext::Delegate* delegate,
-        bool skip_system_calls) override {
+        PrintingContext::ProcessBehavior process_behavior) override {
       auto context =
-          std::make_unique<TestPrintingContext>(delegate, skip_system_calls);
+          std::make_unique<TestPrintingContext>(delegate, process_behavior);
 
       auto settings = std::make_unique<PrintSettings>();
       settings->set_copies(kPrintSettingsCopies);
diff --git a/chrome/browser/printing/printer_query.cc b/chrome/browser/printing/printer_query.cc
index 9fefdc15..888fcc3 100644
--- a/chrome/browser/printing/printer_query.cc
+++ b/chrome/browser/printing/printer_query.cc
@@ -45,12 +45,13 @@
 
 namespace {
 
-bool ShouldPrintingContextSkipSystemCalls() {
+PrintingContext::ProcessBehavior GetPrintingContextProcessBehavior() {
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
-  return features::ShouldPrintJobOop();
-#else
-  return false;
+  if (features::ShouldPrintJobOop()) {
+    return PrintingContext::ProcessBehavior::kOopEnabledSkipSystemCalls;
+  }
 #endif
+  return PrintingContext::ProcessBehavior::kOopDisabled;
 }
 
 class PrintingContextDelegate : public PrintingContext::Delegate {
@@ -119,7 +120,7 @@
           std::make_unique<PrintingContextDelegate>(rfh_id)),
       printing_context_(
           PrintingContext::Create(printing_context_delegate_.get(),
-                                  ShouldPrintingContextSkipSystemCalls())),
+                                  GetPrintingContextProcessBehavior())),
       rfh_id_(rfh_id),
       cookie_(PrintSettings::NewCookie()) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -295,8 +296,8 @@
   // The purpose of `print_context` is to set the default printable area. To do
   // so, it doesn't need a RFH, so just default initialize the RFH id.
   PrintingContextDelegate delegate((content::GlobalRenderFrameHostId()));
-  std::unique_ptr<PrintingContext> print_context =
-      PrintingContext::Create(&delegate, /*skip_system_calls=*/false);
+  std::unique_ptr<PrintingContext> print_context = PrintingContext::Create(
+      &delegate, PrintingContext::ProcessBehavior::kOopDisabled);
   print_context->SetPrintSettings(print_settings);
   print_context->SetDefaultPrintableAreaForVirtualPrinters();
   print_settings = print_context->settings();
diff --git a/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_history_sync_step.xml b/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_history_sync_step.xml
index 00dfa2a..4c99c18 100644
--- a/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_history_sync_step.xml
+++ b/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_history_sync_step.xml
@@ -28,14 +28,12 @@
             android:src="@drawable/privacy_guide_history_sync_image"
             android:importantForAccessibility="no" />
 
-        <com.google.android.material.switchmaterial.SwitchMaterial
+        <org.chromium.components.browser_ui.widget.MaterialSwitchWithText
             android:id="@+id/history_sync_switch"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:paddingHorizontal="@dimen/all_content_marginHorizontal"
-            android:showText="false"
             android:text="@string/privacy_guide_history_sync_toggle"
-            android:textAppearance="@style/TextAppearance.TextLarge.Primary"
             android:foreground="?attr/selectableItemBackground"
             android:background="@null" />
 
diff --git a/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_msbb_step.xml b/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_msbb_step.xml
index a6b32998..ccdc7f5 100644
--- a/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_msbb_step.xml
+++ b/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_msbb_step.xml
@@ -28,14 +28,12 @@
             android:src="@drawable/privacy_guide_msbb_image"
             android:importantForAccessibility="no" />
 
-        <com.google.android.material.switchmaterial.SwitchMaterial
+        <org.chromium.components.browser_ui.widget.MaterialSwitchWithText
             android:id="@+id/msbb_switch"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:paddingHorizontal="@dimen/all_content_marginHorizontal"
-            android:showText="false"
             android:text="@string/url_keyed_anonymized_data_title"
-            android:textAppearance="@style/TextAppearance.TextLarge.Primary"
             android:foreground="?attr/selectableItemBackground"
             android:background="@null" />
 
diff --git a/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_msbb_v3_step.xml b/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_msbb_v3_step.xml
index cc27110..064ecd6 100644
--- a/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_msbb_v3_step.xml
+++ b/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_msbb_v3_step.xml
@@ -28,14 +28,12 @@
             android:src="@drawable/privacy_guide_msbb_image"
             android:importantForAccessibility="no" />
 
-        <com.google.android.material.switchmaterial.SwitchMaterial
+        <org.chromium.components.browser_ui.widget.MaterialSwitchWithText
             android:id="@+id/msbb_switch"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:paddingHorizontal="@dimen/all_content_marginHorizontal"
-            android:showText="false"
             android:text="@string/url_keyed_anonymized_data_title"
-            android:textAppearance="@style/TextAppearance.TextLarge.Primary"
             android:foreground="?attr/selectableItemBackground"
             android:background="@null" />
 
diff --git a/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_search_suggestions_step.xml b/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_search_suggestions_step.xml
index 2afb93f..060922d 100644
--- a/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_search_suggestions_step.xml
+++ b/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_search_suggestions_step.xml
@@ -27,14 +27,12 @@
             android:src="@drawable/privacy_guide_search_suggestions_image"
             android:importantForAccessibility="no" />
 
-        <com.google.android.material.switchmaterial.SwitchMaterial
+        <org.chromium.components.browser_ui.widget.MaterialSwitchWithText
             android:id="@+id/search_suggestions_switch"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:paddingHorizontal="@dimen/all_content_marginHorizontal"
-            android:showText="false"
             android:text="@string/improve_search_suggestions_title"
-            android:textAppearance="@style/TextAppearance.TextLarge.Primary"
             android:foreground="?attr/selectableItemBackground"
             android:background="@null" />
 
diff --git a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/HistorySyncFragment.java b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/HistorySyncFragment.java
index fce1d3f..b3f596e 100644
--- a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/HistorySyncFragment.java
+++ b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/HistorySyncFragment.java
@@ -12,9 +12,9 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.appcompat.widget.SwitchCompat;
 
 import org.chromium.chrome.browser.sync.SyncServiceFactory;
+import org.chromium.components.browser_ui.widget.MaterialSwitchWithText;
 import org.chromium.components.sync.SyncService;
 import org.chromium.components.sync.UserSelectableType;
 
@@ -39,7 +39,7 @@
         mSyncService = SyncServiceFactory.getForProfile(getProfile());
         mInitialKeepEverythingSynced = mSyncService.hasKeepEverythingSynced();
 
-        SwitchCompat historySyncSwitch = view.findViewById(R.id.history_sync_switch);
+        MaterialSwitchWithText historySyncSwitch = view.findViewById(R.id.history_sync_switch);
         historySyncSwitch.setChecked(PrivacyGuideUtils.isHistorySyncEnabled(getProfile()));
 
         historySyncSwitch.setOnCheckedChangeListener(this);
diff --git a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/MSBBFragment.java b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/MSBBFragment.java
index 1c755303..0f5f750 100644
--- a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/MSBBFragment.java
+++ b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/MSBBFragment.java
@@ -9,10 +9,9 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import androidx.appcompat.widget.SwitchCompat;
-
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.signin.services.UnifiedConsentServiceBridge;
+import org.chromium.components.browser_ui.widget.MaterialSwitchWithText;
 
 /**
  * Controls the behaviour of the MSBB privacy guide page.
@@ -28,7 +27,7 @@
 
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
-        SwitchCompat msbbSwitch = view.findViewById(R.id.msbb_switch);
+        MaterialSwitchWithText msbbSwitch = view.findViewById(R.id.msbb_switch);
         msbbSwitch.setChecked(PrivacyGuideUtils.isMsbbEnabled(getProfile()));
 
         msbbSwitch.setOnCheckedChangeListener((button, isChecked) -> {
diff --git a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/SearchSuggestionsFragment.java b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/SearchSuggestionsFragment.java
index 7d27eb6..7ec051f 100644
--- a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/SearchSuggestionsFragment.java
+++ b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/SearchSuggestionsFragment.java
@@ -9,9 +9,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import androidx.appcompat.widget.SwitchCompat;
-
 import org.chromium.chrome.browser.preferences.Pref;
+import org.chromium.components.browser_ui.widget.MaterialSwitchWithText;
 import org.chromium.components.user_prefs.UserPrefs;
 
 /**
@@ -26,7 +25,8 @@
 
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
-        SwitchCompat searchSuggestionsSwitch = view.findViewById(R.id.search_suggestions_switch);
+        MaterialSwitchWithText searchSuggestionsSwitch =
+                view.findViewById(R.id.search_suggestions_switch);
         searchSuggestionsSwitch.setChecked(
                 PrivacyGuideUtils.isSearchSuggestionsEnabled(getProfile()));
 
diff --git a/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/HistorySyncFragmentTest.java b/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/HistorySyncFragmentTest.java
index 61086bf..c7d65b7 100644
--- a/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/HistorySyncFragmentTest.java
+++ b/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/HistorySyncFragmentTest.java
@@ -13,7 +13,6 @@
 
 import android.os.Bundle;
 
-import androidx.appcompat.widget.SwitchCompat;
 import androidx.fragment.app.testing.FragmentScenario;
 
 import org.junit.After;
@@ -30,6 +29,7 @@
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.UserActionTester;
 import org.chromium.chrome.browser.sync.SyncServiceFactory;
+import org.chromium.components.browser_ui.widget.MaterialSwitchWithText;
 import org.chromium.components.sync.SyncService;
 import org.chromium.components.sync.UserSelectableType;
 
@@ -51,7 +51,7 @@
     @Captor private ArgumentCaptor<Set<Integer>> mSetCaptor;
 
     private FragmentScenario mScenario;
-    private SwitchCompat mHistorySyncButton;
+    private MaterialSwitchWithText mHistorySyncButton;
     private final UserActionTester mActionTester = new UserActionTester();
 
     @Before
diff --git a/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/MSBBFragmentTest.java b/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/MSBBFragmentTest.java
index e15c20a..ce10242 100644
--- a/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/MSBBFragmentTest.java
+++ b/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/MSBBFragmentTest.java
@@ -10,7 +10,6 @@
 import android.os.Bundle;
 
 import androidx.annotation.NonNull;
-import androidx.appcompat.widget.SwitchCompat;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentFactory;
 import androidx.fragment.app.testing.FragmentScenario;
@@ -34,6 +33,7 @@
 import org.chromium.chrome.browser.signin.services.UnifiedConsentServiceBridgeJni;
 import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
+import org.chromium.components.browser_ui.widget.MaterialSwitchWithText;
 
 /** JUnit tests of the class {@link MSBBFragment}. */
 @RunWith(BaseRobolectricTestRunner.class)
@@ -45,7 +45,7 @@
     @Mock private UnifiedConsentServiceBridge.Natives mNativeMock;
 
     private FragmentScenario mScenario;
-    private SwitchCompat mMSBBButton;
+    private MaterialSwitchWithText mMSBBButton;
     private final UserActionTester mActionTester = new UserActionTester();
 
     @Before
diff --git a/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/SearchSuggestionsFragmentTest.java b/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/SearchSuggestionsFragmentTest.java
index 6844e89..eb83718a 100644
--- a/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/SearchSuggestionsFragmentTest.java
+++ b/chrome/browser/privacy_guide/android/junit/src/org/chromium/chrome/browser/privacy_guide/SearchSuggestionsFragmentTest.java
@@ -12,7 +12,6 @@
 import android.os.Bundle;
 
 import androidx.annotation.NonNull;
-import androidx.appcompat.widget.SwitchCompat;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentFactory;
 import androidx.fragment.app.testing.FragmentScenario;
@@ -31,6 +30,7 @@
 import org.chromium.base.test.util.UserActionTester;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.components.browser_ui.widget.MaterialSwitchWithText;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.components.user_prefs.UserPrefsJni;
@@ -46,7 +46,7 @@
     @Mock private PrefService mPrefService;
 
     private FragmentScenario mScenario;
-    private SwitchCompat mSearchSuggestionsButton;
+    private MaterialSwitchWithText mSearchSuggestionsButton;
     private final UserActionTester mActionTester = new UserActionTester();
 
     @Before
@@ -70,7 +70,7 @@
                 FragmentScenario.launchInContainer(
                         SearchSuggestionsFragment.class,
                         Bundle.EMPTY,
-                        R.style.Theme_MaterialComponents,
+                        org.chromium.chrome.R.style.Theme_BrowserUI_DayNight,
                         new FragmentFactory() {
                             @NonNull
                             @Override
diff --git a/chrome/browser/readaloud/android/java/res/layout/readaloud_expanded_player_layout.xml b/chrome/browser/readaloud/android/java/res/layout/readaloud_expanded_player_layout.xml
index 523fa27..2e816ea 100644
--- a/chrome/browser/readaloud/android/java/res/layout/readaloud_expanded_player_layout.xml
+++ b/chrome/browser/readaloud/android/java/res/layout/readaloud_expanded_player_layout.xml
@@ -18,12 +18,6 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="horizontal">
-        <!-- This empty view balances the close button so the drag handlebar and "Chrome now playing" can be centered. -->
-        <View
-            android:layout_width="@dimen/readaloud_close_button_size"
-            android:layout_height="@dimen/readaloud_close_button_size"
-            android:layout_margin="@dimen/readaloud_close_button_margin"
-            android:layout_weight="0"/>
         <LinearLayout
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
@@ -47,14 +41,6 @@
                 android:text="@string/readaloud_chrome_now_playing"
                 android:textAppearance="@style/TextAppearance.TextMedium.Secondary"/>
         </LinearLayout>
-        <ImageView
-            android:id="@+id/readaloud_expanded_player_close_button"
-            android:src="@drawable/baseline_close_24"
-            android:contentDescription="@string/readaloud_close_player_button_content_description"
-            android:layout_width="@dimen/readaloud_close_button_size"
-            android:layout_height="@dimen/readaloud_close_button_size"
-            android:layout_margin="@dimen/readaloud_close_button_margin"
-            android:layout_weight="0"/>
     </LinearLayout>
 
     <LinearLayout
diff --git a/chrome/browser/readaloud/android/java/res/layout/readaloud_toggle_switch.xml b/chrome/browser/readaloud/android/java/res/layout/readaloud_toggle_switch.xml
index 73efbc8..708b7eb 100644
--- a/chrome/browser/readaloud/android/java/res/layout/readaloud_toggle_switch.xml
+++ b/chrome/browser/readaloud/android/java/res/layout/readaloud_toggle_switch.xml
@@ -4,7 +4,7 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<com.google.android.material.switchmaterial.SwitchMaterial
+<com.google.android.material.materialswitch.MaterialSwitch
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/toggle_switch"
     android:layout_width="wrap_content"
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediator.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediator.java
index 60eb60c..6f0af4ed 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediator.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediator.java
@@ -20,6 +20,8 @@
 
 /** Mediator class in charge of updating player UI property model. */
 class PlayerMediator implements InteractionHandler {
+    private static final long SEEK_BACK_NANOS = -10 * 1_000_000_000L;
+    private static final long SEEK_FORWARD_NANOS = 30 * 1_000_000_000L;
     private final PlayerCoordinator mCoordinator;
     private final PlayerCoordinator.Delegate mDelegate;
     private final PropertyModel mModel;
@@ -32,6 +34,8 @@
                             (float) data.absolutePositionNanos()
                                     / (float) data.totalDurationNanos();
                     mModel.set(PlayerProperties.PROGRESS, percent);
+                    mModel.set(PlayerProperties.ELAPSED_NANOS, data.absolutePositionNanos());
+                    mModel.set(PlayerProperties.DURATION_NANOS, data.totalDurationNanos());
                 }
             };
 
@@ -102,10 +106,14 @@
     public void onPublisherClick() {}
 
     @Override
-    public void onSeekBackClick() {}
+    public void onSeekBackClick() {
+        maybeSeekRelative(SEEK_BACK_NANOS);
+    }
 
     @Override
-    public void onSeekForwardClick() {}
+    public void onSeekForwardClick() {
+        maybeSeekRelative(SEEK_FORWARD_NANOS);
+    }
 
     @Override
     public void onVoiceSelected(PlaybackVoice voice) {
@@ -142,4 +150,17 @@
     public void onMiniPlayerExpandClick() {
         mCoordinator.expand();
     }
+
+    private void maybeSeekRelative(long nanos) {
+        if (mPlayback == null) {
+            return;
+        }
+        if (mModel.get(PlayerProperties.ELAPSED_NANOS) + nanos
+                >= mModel.get(PlayerProperties.DURATION_NANOS)) {
+            mPlayback.pause();
+            mPlayback.seek(mModel.get(PlayerProperties.DURATION_NANOS));
+        } else {
+            mPlayback.seekRelative(nanos);
+        }
+    }
 }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediatorUnitTest.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediatorUnitTest.java
index 5b4d82d1..d1be148 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediatorUnitTest.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediatorUnitTest.java
@@ -6,8 +6,10 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 
@@ -286,6 +288,41 @@
     }
 
     @Test
+    public void testOnSeekBack() {
+        // make sure nothing happens if playback hasn't been set yet
+        mMediator.setPlayback(null);
+        mMediator.onSeekBackClick();
+        verify(mPlayback, never()).seekRelative(anyLong());
+
+        mModel.set(PlayerProperties.ELAPSED_NANOS, 0L);
+        mModel.set(PlayerProperties.DURATION_NANOS, 40 * 1_000_000_000L);
+        mMediator.setPlayback(mPlayback);
+        mMediator.onSeekBackClick();
+        verify(mPlayback).seekRelative(-10 * 1_000_000_000L);
+    }
+
+    @Test
+    public void testOnSeekForward() {
+        mMediator.setPlayback(mPlayback);
+        mModel.set(PlayerProperties.ELAPSED_NANOS, 0L);
+        mModel.set(PlayerProperties.DURATION_NANOS, 40 * 1_000_000_000L);
+
+        mMediator.onSeekForwardClick();
+        verify(mPlayback).seekRelative(30 * 1_000_000_000L);
+    }
+
+    @Test
+    public void testOnSeekForwardPastEnd() {
+        // Set playback duration shorter to test the pause at end when seeking beyond duration
+        mMediator.setPlayback(mPlayback);
+        mModel.set(PlayerProperties.ELAPSED_NANOS, 0L);
+        mModel.set(PlayerProperties.DURATION_NANOS, 1L);
+        mMediator.onSeekForwardClick();
+        verify(mPlayback).pause();
+        verify(mPlayback).seek(1L);
+    }
+
+    @Test
     public void testOnMiniPlayerExpandClick() {
         mMediator.onMiniPlayerExpandClick();
         verify(mPlayerCoordinator).expand();
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerProperties.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerProperties.java
index c6aa559..837409d 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerProperties.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/PlayerProperties.java
@@ -25,6 +25,10 @@
     public static final WritableObjectPropertyKey<Float> PROGRESS =
             new WritableObjectPropertyKey<>();
     public static final WritableObjectPropertyKey<Float> SPEED = new WritableObjectPropertyKey<>();
+    public static final WritableObjectPropertyKey<Long> ELAPSED_NANOS =
+            new WritableObjectPropertyKey<>();
+    public static final WritableObjectPropertyKey<Long> DURATION_NANOS =
+            new WritableObjectPropertyKey<>();
     public static final WritableObjectPropertyKey<InteractionHandler> INTERACTION_HANDLER =
             new WritableObjectPropertyKey<>();
     public static final WritableObjectPropertyKey<MiniPlayerMediator> MINI_PLAYER_MEDIATOR =
@@ -39,6 +43,8 @@
         PROGRESS, //
         MINI_PLAYER_MEDIATOR, //
         SPEED, //
+        ELAPSED_NANOS, //
+        DURATION_NANOS, //
         INTERACTION_HANDLER //
     };
 }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContent.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContent.java
index c2e94fdf..185bd16 100644
--- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContent.java
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/expanded/ExpandedPlayerSheetContent.java
@@ -87,7 +87,6 @@
     }
 
     void setInteractionHandler(InteractionHandler handler) {
-        setOnClickListener(R.id.readaloud_expanded_player_close_button, handler::onCloseClick);
         setOnClickListener(R.id.readaloud_play_pause_button, handler::onPlayPauseClick);
         setOnClickListener(R.id.readaloud_seek_back_button, handler::onSeekBackClick);
         setOnClickListener(R.id.readaloud_seek_forward_button, handler::onSeekForwardClick);
diff --git a/chrome/browser/resource_coordinator/BUILD.gn b/chrome/browser/resource_coordinator/BUILD.gn
index a3009c2..288f1d26 100644
--- a/chrome/browser/resource_coordinator/BUILD.gn
+++ b/chrome/browser/resource_coordinator/BUILD.gn
@@ -9,7 +9,6 @@
 mojom("mojo_bindings") {
   sources = [ "lifecycle_unit_state.mojom" ]
   webui_module_path = "/"
-  use_typescript_sources = true
 }
 
 source_set("tab_manager_features") {
diff --git a/chrome/browser/resources/ash/settings/internet_page/internet_page.html b/chrome/browser/resources/ash/settings/internet_page/internet_page.html
index 71d16e4..9ea6731 100644
--- a/chrome/browser/resources/ash/settings/internet_page/internet_page.html
+++ b/chrome/browser/resources/ash/settings/internet_page/internet_page.html
@@ -131,6 +131,7 @@
           <cr-button id="createCustomApnButton"
               on-click="onCreateCustomApnClicked_"
               class="cancel-button"
+              deep-link-focus-id$="[[Setting.kCellularAddApn]]"
               disabled="[[isCreateCustomApnButtonDisabled_]]">
             <iron-icon icon="cr:add" slot="prefix-icon"></iron-icon>
             $i18n{apnPageAddNewApn}
diff --git a/chrome/browser/resources/ash/settings/internet_page/internet_page.ts b/chrome/browser/resources/ash/settings/internet_page/internet_page.ts
index 4aa8c0f..a64cad9a 100644
--- a/chrome/browser/resources/ash/settings/internet_page/internet_page.ts
+++ b/chrome/browser/resources/ash/settings/internet_page/internet_page.ts
@@ -301,6 +301,7 @@
         value: () => new Set<Setting>([
           Setting.kWifiOnOff,
           Setting.kMobileOnOff,
+          Setting.kCellularAddApn,
         ]),
       },
 
@@ -475,6 +476,8 @@
       networkType = NetworkType.kWiFi;
     } else if (settingId === Setting.kMobileOnOff) {
       networkType = NetworkType.kCellular;
+    } else {
+      return true;
     }
 
     afterNextRender(this, () => {
@@ -500,7 +503,7 @@
   override currentRouteChanged(newRoute: Route, oldRoute?: Route): void {
     super.currentRouteChanged(newRoute, oldRoute);
 
-    if (newRoute === this.route) {
+    if (newRoute === this.route || newRoute === routes.APN) {
       // Show deep links for the internet page.
       this.attemptDeepLink();
     } else if (newRoute === routes.INTERNET_NETWORKS) {
diff --git a/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts b/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts
index b881da2..cb7a6527 100644
--- a/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts
+++ b/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts
@@ -364,6 +364,7 @@
           path: `/${routesMojom.ACCESSIBILITY_SECTION_PATH}`,
           icon: 'os-settings:accessibility-revamp',
           label: this.i18n('a11yPageTitle'),
+          sublabel: this.i18n('a11yMenuItemDescription'),
         },
         {
           section: Section.kSystemPreferences,
diff --git a/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.html b/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.html
index 3ea3adb..a73a8dc 100644
--- a/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.html
+++ b/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.html
@@ -4,23 +4,14 @@
   }
 
   :host([selected]) [focus-row-container] {
-    background-color: var(--cros-highlight-color);
-  }
-
-  :host-context(body.jelly-enabled):host([selected]) [focus-row-container] {
     background-color: var(--cros-sys-highlight_shape);
   }
 
   :host(:not([selected])) [focus-row-container]:hover {
-    background-color: var(--cros-highlight-color-hover);
-  }
-
-  :host-context(body.jelly-enabled):host(:not([selected]))
-      [focus-row-container]:hover {
     background-color: var(--cros-sys-hover_on_subtle);
   }
 
-  :host-context(body.jelly-enabled) [focus-row-control][selectable]:focus {
+  [focus-row-control][selectable]:focus {
     background-color: var(--cros-sys-ripple_neutral_on_subtle);
   }
 
@@ -51,10 +42,6 @@
 
   /* Bolding occurs in the JS. */
   b {
-    color: var(--cros-text-color-primary);
-  }
-
-  :host-context(body.jelly-enabled) b {
     color: var(--cros-sys-on_surface);
   }
 </style>
diff --git a/chrome/browser/resources/ash/settings/os_settings_search_box/os_settings_search_box.html b/chrome/browser/resources/ash/settings/os_settings_search_box/os_settings_search_box.html
index 188640d..0b8102cf 100644
--- a/chrome/browser/resources/ash/settings/os_settings_search_box/os_settings_search_box.html
+++ b/chrome/browser/resources/ash/settings/os_settings_search_box/os_settings_search_box.html
@@ -1,7 +1,6 @@
 <style include="settings-shared">
   :host {
-    --cr-toolbar-search-field-background:
-        var(--cros-toolbar-search-bg-color);
+    --cr-toolbar-search-field-background: var(--cros-sys-input_field_on_shaded);
     --cr-toolbar-focused-min-height: 40px;
     --cr-toolbar-icon-container-size: 32px;
     --cr-toolbar-icon-margin: 8px 16px;
@@ -19,10 +18,6 @@
     width: var(--cr-toolbar-field-width);
   }
 
-  :host-context(body.jelly-enabled):host {
-    --cr-toolbar-search-field-background: var(--cros-sys-input_field_on_shaded);
-  }
-
   @media (prefers-color-scheme: dark) {
     :host {
       --cr-toolbar-search-field-narrow-mode-prompt-opacity: 1;
@@ -129,23 +124,15 @@
     margin-inline-start: 8px;
   }
 
-  /* The separator covers the top box shadow of the dropdown so that
-    * var(--cr-elevation-3) can be used instead of custom values. */
+  /* The separator covers the top box shadow of the dropdown. */
   .separator {
     background-color: var(--cros-bg-color-elevation-3);
-    border-bottom: none;
-    border-inline-end: none;
-    border-inline-start: none;
-    border-top: 1px solid var(--cros-separator-color);
+    border-top: 1px solid var(--cros-sys-separator);
     height: var(--separator-height);
     margin-inline-end: 0;
     margin-inline-start: 0;
     margin-top: -9px;
   }
-
-  :host-context(body.jelly-enabled) .separator {
-    border-color: var(--cros-sys-separator);
-  }
 </style>
 <cr-toolbar-search-field id="search" narrow="[[narrow]]"
     on-search-icon-clicked="onSearchIconClicked_"
diff --git a/chrome/browser/resources/ash/settings/os_toolbar/os_toolbar.html b/chrome/browser/resources/ash/settings/os_toolbar/os_toolbar.html
index 6eea5377..8d49482 100644
--- a/chrome/browser/resources/ash/settings/os_toolbar/os_toolbar.html
+++ b/chrome/browser/resources/ash/settings/os_toolbar/os_toolbar.html
@@ -1,17 +1,13 @@
 <style include="cr-icons cr-hidden-style">
   :host {
     align-items: center;
-    background-color: var(--cros-bg-color);
+    background-color: var(--cros-sys-app_base_shaded);
     color: var(--cros-text-color-secondary);
     display: flex;
     height: var(--cr-toolbar-height);
     padding-top: var(--cr-toolbar-padding-top);
   }
 
-  :host-context(body.jelly-enabled):host {
-    background-color: var(--cros-sys-app_base_shaded);
-  }
-
   h1 {
     flex: 1;
     font-size: 123%;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_range.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_range.js
index 2cf096f0..59676ace 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_range.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_range.js
@@ -8,9 +8,11 @@
 import {AutomationPredicate} from '../../common/automation_predicate.js';
 import {AutomationUtil} from '../../common/automation_util.js';
 import {constants} from '../../common/constants.js';
+import {Cursor} from '../../common/cursors/cursor.js';
 import {CursorRange} from '../../common/cursors/range.js';
 import {BridgeConstants} from '../common/bridge_constants.js';
 import {BridgeHelper} from '../common/bridge_helper.js';
+import {EarconId} from '../common/earcon_id.js';
 import {TtsSpeechProperties} from '../common/tts_types.js';
 
 import {ChromeVox} from './chromevox.js';
@@ -120,6 +122,14 @@
     ChromeVoxRange.instance.set_(...arguments);
   }
 
+  /**
+   * @return {boolean} true if the selection is toggled on, false if it is
+   * toggled off.
+   */
+  static toggleSelection() {
+    return ChromeVoxRange.instance.toggleSelection_();
+  }
+
   // ================= Observer Functions =================
 
   /** @param {ChromeVoxRangeObserver} observer */
@@ -406,6 +416,44 @@
       start.setSequentialFocusNavigationStartingPoint();
     }
   }
+
+  /**
+   * @return {boolean} true if the selection is toggled on, false if it is
+   * toggled off.
+   * @private
+   */
+  toggleSelection_() {
+    if (!ChromeVoxRange.pageSel) {
+      ChromeVox.earcons.playEarcon(EarconId.SELECTION);
+      ChromeVoxRange.pageSel = ChromeVoxRange.current;
+      DesktopAutomationInterface.instance.ignoreDocumentSelectionFromAction(
+          true);
+      return true;
+    } else {
+      const root = ChromeVoxRange.current.start.node.root;
+      if (root && root.selectionStartObject && root.selectionEndObject &&
+          !isNaN(Number(root.selectionStartOffset)) &&
+          !isNaN(Number(root.selectionEndOffset))) {
+        ChromeVox.earcons.playEarcon(EarconId.SELECTION_REVERSE);
+        const sel = new CursorRange(
+            new Cursor(
+                root.selectionStartObject,
+                /** @type {number} */ (root.selectionStartOffset)),
+            new Cursor(
+                root.selectionEndObject,
+                /** @type {number} */ (root.selectionEndOffset)));
+        const o =
+            new Output()
+                .format('@end_selection')
+                .withSpeechAndBraille(sel, sel, OutputCustomEvent.NAVIGATE)
+                .go();
+        DesktopAutomationInterface.instance.ignoreDocumentSelectionFromAction(
+            false);
+      }
+      ChromeVoxRange.pageSel = null;
+      return false;
+    }
+  }
 }
 
 /** @private {!Array<ChromeVoxRangeObserver>} */
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/command_handler.js
index 2c3a778..2575950 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/command_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/input/command_handler.js
@@ -572,7 +572,8 @@
         new Output().withString(node.root.docUrl || '').go();
         return false;
       case Command.TOGGLE_SELECTION:
-        if (!this.toggleSelection_()) {
+        // If the selection was toggled off, return.
+        if (!ChromeVoxRange.toggleSelection()) {
           return false;
         }
         break;
@@ -1628,43 +1629,6 @@
   }
 
   /**
-   * @return {boolean} whether execution should continue.
-   * @private
-   */
-  toggleSelection_() {
-    if (!ChromeVoxRange.pageSel) {
-      ChromeVox.earcons.playEarcon(EarconId.SELECTION);
-      ChromeVoxRange.pageSel = ChromeVoxRange.current;
-      DesktopAutomationInterface.instance.ignoreDocumentSelectionFromAction(
-          true);
-    } else {
-      const root = ChromeVoxRange.current.start.node.root;
-      if (root && root.selectionStartObject && root.selectionEndObject &&
-          !isNaN(Number(root.selectionStartOffset)) &&
-          !isNaN(Number(root.selectionEndOffset))) {
-        ChromeVox.earcons.playEarcon(EarconId.SELECTION_REVERSE);
-        const sel = new CursorRange(
-            new Cursor(
-                root.selectionStartObject,
-                /** @type {number} */ (root.selectionStartOffset)),
-            new Cursor(
-                root.selectionEndObject,
-                /** @type {number} */ (root.selectionEndOffset)));
-        const o =
-            new Output()
-                .format('@end_selection')
-                .withSpeechAndBraille(sel, sel, OutputCustomEvent.NAVIGATE)
-                .go();
-        DesktopAutomationInterface.instance.ignoreDocumentSelectionFromAction(
-            false);
-      }
-      ChromeVoxRange.pageSel = null;
-      return false;
-    }
-    return true;
-  }
-
-  /**
    * Performs global initialization.
    */
   static init() {
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js
index 3539230..b08360a7 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js
@@ -8,7 +8,7 @@
 import {Navigator} from './navigator.js';
 import {SAChildNode, SARootNode} from './nodes/switch_access_node.js';
 import {SwitchAccess} from './switch_access.js';
-import {ActionResponse, MenuType, Mode} from './switch_access_constants.js';
+import {ActionResponse, ErrorType, MenuType, Mode} from './switch_access_constants.js';
 
 const MenuAction = chrome.accessibilityPrivate.SwitchAccessMenuAction;
 
@@ -33,11 +33,13 @@
     this.menuStack_ = [];
   }
 
-  static get instance() {
-    if (!ActionManager.instance_) {
-      ActionManager.instance_ = new ActionManager();
+  static init() {
+    if (ActionManager.instance) {
+      throw SwitchAccess.error(
+          ErrorType.DUPLICATE_INITIALIZATION,
+          'Cannot call ActionManager.init() more than once.');
     }
-    return ActionManager.instance_;
+    ActionManager.instance = new ActionManager();
   }
 
   // ================= Static Methods ==================
@@ -318,3 +320,6 @@
     }
   }
 }
+
+/** @type {ActionManager} */
+ActionManager.instance;
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
index 35fd2e3..33b8ac58 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
@@ -24,6 +24,12 @@
  * codebase.
  */
 export class SwitchAccess {
+  /** @private */
+  constructor() {
+    /* @private {!Mode} */
+    this.mode_ = Mode.ITEM_SCAN;
+  }
+
   /** @param {!AutomationNode} desktop */
   static async init(desktop) {
     if (SwitchAccess.instance) {
@@ -47,47 +53,6 @@
   }
 
   /**
-   * @param {!AutomationNode} desktop
-   * @param {AutomationNode} currentFocus
-   * @private
-   */
-  async waitForFocus_(desktop, currentFocus) {
-    return new Promise(resolve => {
-      // Focus is available. Finish init without waiting for further events.
-      // Disallow web view nodes, which indicate a root web area is still
-      // loading and pending focus.
-      if (currentFocus && currentFocus.role !== RoleType.WEB_VIEW) {
-        resolve();
-        return;
-      }
-
-      // Wait for the focus to be sent. If |currentFocus| was undefined, this is
-      // guaranteed. Otherwise, also set a timed callback to ensure we do
-      // eventually init.
-      let callbackId = 0;
-      const listener = maybeEvent => {
-        if (maybeEvent && maybeEvent.target.role === RoleType.WEB_VIEW) {
-          return;
-        }
-
-        desktop.removeEventListener(EventType.FOCUS, listener, false);
-        clearTimeout(callbackId);
-
-        resolve();
-      };
-
-      desktop.addEventListener(EventType.FOCUS, listener, false);
-      callbackId = setTimeout(listener, 5000);
-    });
-  }
-
-  /** @private */
-  constructor() {
-    /* @private {!Mode} */
-    this.mode_ = Mode.ITEM_SCAN;
-  }
-
-  /**
    * Returns whether or not the feature flag
    * for improved text input is enabled.
    * @return {boolean}
@@ -162,6 +127,41 @@
         /** @type {number} */ (errorType), errorTypeCountForUMA);
     return new Error(errorString);
   }
+
+  /**
+   * @param {!AutomationNode} desktop
+   * @param {AutomationNode} currentFocus
+   * @private
+   */
+  async waitForFocus_(desktop, currentFocus) {
+    return new Promise(resolve => {
+      // Focus is available. Finish init without waiting for further events.
+      // Disallow web view nodes, which indicate a root web area is still
+      // loading and pending focus.
+      if (currentFocus && currentFocus.role !== RoleType.WEB_VIEW) {
+        resolve();
+        return;
+      }
+
+      // Wait for the focus to be sent. If |currentFocus| was undefined, this is
+      // guaranteed. Otherwise, also set a timed callback to ensure we do
+      // eventually init.
+      let callbackId = 0;
+      const listener = maybeEvent => {
+        if (maybeEvent && maybeEvent.target.role === RoleType.WEB_VIEW) {
+          return;
+        }
+
+        desktop.removeEventListener(EventType.FOCUS, listener, false);
+        clearTimeout(callbackId);
+
+        resolve();
+      };
+
+      desktop.addEventListener(EventType.FOCUS, listener, false);
+      callbackId = setTimeout(listener, 5000);
+    });
+  }
 }
 
 /** @type {SwitchAccess} */
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_constants.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_constants.js
index 29203a4..52e1bbc 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_constants.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_constants.js
@@ -45,6 +45,7 @@
   PREVIOUS_INVALID: 14,
   INVALID_SELECTION_BOUNDS: 15,
   UNINITIALIZED: 16,
+  DUPLICATE_INITIALIZATION: 17,
 };
 
 /**
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access_loader.js b/chrome/browser/resources/chromeos/accessibility/switch_access_loader.js
index 23d47fa..f20e9068 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access_loader.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access_loader.js
@@ -5,6 +5,7 @@
 import {AsyncUtil} from './common/async_util.js';
 import {Flags} from './common/flags.js';
 import {InstanceChecker} from './common/instance_checker.js';
+import {ActionManager} from './switch_access/action_manager.js';
 import {SACommands} from './switch_access/commands.js';
 import {Navigator} from './switch_access/navigator.js';
 import {SettingsManager} from './switch_access/settings_manager.js';
@@ -20,6 +21,7 @@
   // Navigator must be initialized before other classes.
   Navigator.initializeSingletonInstances(desktop);
 
+  ActionManager.init();
   SACommands.init();
   SettingsManager.init();
 
diff --git a/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.html b/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.html
index eec10627..18bed9c 100644
--- a/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.html
+++ b/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.html
@@ -1,11 +1,12 @@
 <style>
   .controls {
     display: flex;
-    flex-wrap: wrap;
+    flex-wrap: nowrap;
     font-family: monospace;
     font-weight: bold;
     gap: 10px;
     padding: 20px;
+    align-items: center;
   }
 
   .prefix {
@@ -13,6 +14,12 @@
     padding-inline-end: 5px;
   }
 
+  .download-button, .select-filter {
+    height: 30px;
+    margin-bottom: 5px;
+    width: 150px;
+  }
+
   .erp-type {
     min-width: 100px;
   }
@@ -87,9 +94,15 @@
 </style>
 
 <div class="controls">
-  <span class="prefix">History [[loggingStateToString(loggingState)]]</span>
+  <span class="prefix">History: [[loggingStateToString(loggingState)]]</span>
   <cr-toggle checked="{{loggingState}}" on-change="onToggleChange"></cr-toggle>
-  <button on-click="onDownloadButtonClick">Download as CSV</button>
+  <span class="prefix"> Filter by: </span>
+  <select class="select-filter" value="{{selectedOption::change}}">
+    <template is="dom-repeat" items="[[filterOptions]]">
+      <option value="[[item]]">[[item]]</option>
+    </template>
+  </select>
+  <button class="download-button" on-click="onDownloadButtonClick">Download as CSV</button>
 </div>
 <table class="erp-history-table">
   <thead>
diff --git a/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.ts b/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.ts
index 7234f86..72d0d3c 100644
--- a/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.ts
+++ b/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.ts
@@ -27,6 +27,20 @@
   private browserProxy: EnterpriseReportingBrowserProxy =
       EnterpriseReportingBrowserProxy.getInstance();
 
+  // Filtering options for the table.
+  private static allEvents: string = 'All events';
+  private static allButUploads: string = 'All events except uploads';
+  private filterOptions: string[] = [
+    ReportingHistoryElement.allEvents,
+    ReportingHistoryElement.allButUploads,
+    'QueueAction',
+    'Enqueue',
+    'Flush',
+    'Confirm',
+    'Upload',
+  ];
+  private selectedOption: string = ReportingHistoryElement.allEvents;
+
   static get is() {
     return 'reporting-history-element' as const;
   }
@@ -38,13 +52,23 @@
   static get properties() {
     return {
       loggingState: Boolean,
+
+      filterOptions: {
+        type: Array,
+        value: () => [],
+      },
+
+      selectedOption: {
+        type: String,
+        value: '',
+      },
     };
   }
 
   private loggingState: boolean;
 
   loggingStateToString(checked: boolean) {
-    return checked ? 'on' : 'off';
+    return checked ? 'On' : 'Off';
   }
 
   onToggleChange(event: CustomEvent<boolean>) {
@@ -141,9 +165,23 @@
       return;
     }
 
+    // If there are events we filter them by the type of event.
+    const filteredEvents = history.events.filter(
+        (event: ErpHistoryEvent) => event.call == this.selectedOption ||
+            this.selectedOption == ReportingHistoryElement.allEvents ||
+            (this.selectedOption == ReportingHistoryElement.allButUploads &&
+             event.call != 'Upload'));
+
+    // If there are no events after filtering, present the placeholder.
+    if (filteredEvents.length === 0) {
+      this.setEmptyErpTable();
+      return;
+    }
+
     // Populate the table row by the events: iterate through the history
     // in reverse order so that the most recent event shows up first.
-    for (const event of history.events.reverse()) {
+    // This uses the already filtered events by the user selection.
+    for (const event of filteredEvents.reverse()) {
       const row = this.composeTableRow(event);
       this.$.body.appendChild(row);
     }
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn
index 5cd8396a..2bb81d3 100644
--- a/chrome/browser/resources/chromeos/login/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -260,21 +260,17 @@
     "screens/common/autolaunch.js",
     "screens/common/choobe.js",
     "screens/common/consolidated_consent.js",
-    "screens/common/cryptohome_recovery_setup.js",
-    "screens/common/password_selection.js",
     "screens/common/device_disabled.js",
     "screens/common/display_size.js",
     "screens/common/drive_pinning.js",
     "screens/common/enable_kiosk.js",
     "screens/common/error_message.js",
     "screens/common/family_link_notice.js",
-    "screens/common/fingerprint_setup.js",
     "screens/common/gaia_info.js",
     "screens/common/gaia_signin.js",
     "screens/common/gesture_navigation.js",
     "screens/common/guest_tos.js",
     "screens/common/hw_data_collection.js",
-    "screens/common/local_password_setup.js",
     "screens/common/local_state_error.js",
     "screens/common/managed_terms_of_service.js",
     "screens/common/marketing_opt_in.js",
@@ -285,7 +281,6 @@
     "screens/common/os_install.js",
     "screens/common/os_trial.js",
     "screens/common/parental_handoff.js",
-    "screens/common/pin_setup.js",
     "screens/common/remote_activity_notification.js",
 
     # Template used by the `tools/oobe/generate_screen_template.py` script.
@@ -324,6 +319,11 @@
     "screens/oobe/update.js",
     "screens/oobe/welcome.js",
     "screens/oobe/welcome_dialog.js",
+    "screens/osauth/cryptohome_recovery_setup.js",
+    "screens/osauth/fingerprint_setup.js",
+    "screens/osauth/local_password_setup.js",
+    "screens/osauth/password_selection.js",
+    "screens/osauth/pin_setup.js",
   ]
 }
 
@@ -333,6 +333,7 @@
     "screens/common:web_components",
     "screens/login:web_components",
     "screens/oobe:web_components",
+    "screens/osauth:web_components",
   ]
 }
 
@@ -347,9 +348,7 @@
     "screens/common:closure_compile",
     "screens/login:closure_compile",
     "screens/oobe:closure_compile",
-
-    # TODO(antrim): re-enable once files are moved.
-    # t "screens/osauth:closure_compile",
+    "screens/osauth:closure_compile",
     "test_api:closure_compile",
 
     # TODO(crbug.com/1229130)
diff --git a/chrome/browser/resources/chromeos/login/screens.js b/chrome/browser/resources/chromeos/login/screens.js
index 86cc0c88..37888aa 100644
--- a/chrome/browser/resources/chromeos/login/screens.js
+++ b/chrome/browser/resources/chromeos/login/screens.js
@@ -14,20 +14,17 @@
 import './screens/common/autolaunch.js';
 import './screens/common/choobe.js';
 import './screens/common/consolidated_consent.js';
-import './screens/common/cryptohome_recovery_setup.js';
 import './screens/common/device_disabled.js';
 import './screens/common/display_size.js';
 import './screens/common/drive_pinning.js';
 import './screens/common/enable_kiosk.js';
 import './screens/common/error_message.js';
 import './screens/common/family_link_notice.js';
-import './screens/common/fingerprint_setup.js';
 import './screens/common/gaia_info.js';
 import './screens/common/gaia_signin.js';
 import './screens/common/gesture_navigation.js';
 import './screens/common/guest_tos.js';
 import './screens/common/hw_data_collection.js';
-import './screens/common/local_password_setup.js';
 import './screens/common/local_state_error.js';
 import './screens/common/managed_terms_of_service.js';
 import './screens/common/marketing_opt_in.js';
@@ -38,8 +35,6 @@
 import './screens/common/os_install.js';
 import './screens/common/os_trial.js';
 import './screens/common/parental_handoff.js';
-import './screens/common/password_selection.js';
-import './screens/common/pin_setup.js';
 import './screens/common/recommend_apps.js';
 import './screens/common/remote_activity_notification.js';
 import './screens/common/saml_confirm_password.js';
@@ -51,6 +46,12 @@
 import './screens/common/tpm_error.js';
 import './screens/common/user_allowlist_check_screen.js';
 import './screens/common/wrong_hwid.js';
+// COMMON SCREENS USED TO SET UP AUTHENTICATION
+import './screens/osauth/cryptohome_recovery_setup.js';
+import './screens/osauth/fingerprint_setup.js';
+import './screens/osauth/local_password_setup.js';
+import './screens/osauth/password_selection.js';
+import './screens/osauth/pin_setup.js';
 // SCREENS USED DURING THE LOGIN FLOW
 import './screens/login/arc_vm_data_migration.js';
 import './screens/login/cryptohome_recovery.js';
diff --git a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
index 8e167df..5b967f0 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
@@ -35,20 +35,17 @@
     ":autolaunch",
     ":choobe",
     ":consolidated_consent",
-    ":cryptohome_recovery_setup",
     ":device_disabled",
     ":display_size",
     ":drive_pinning",
     ":enable_kiosk",
     ":error_message",
     ":family_link_notice",
-    ":fingerprint_setup",
     ":gaia_info",
     ":gaia_signin",
     ":gesture_navigation",
     ":guest_tos",
     ":hw_data_collection",
-    ":local_password_setup",
     ":local_state_error",
     ":managed_terms_of_service",
     ":marketing_opt_in",
@@ -57,8 +54,6 @@
     ":os_install",
     ":os_trial",
     ":parental_handoff",
-    ":password_selection",
-    ":pin_setup",
     ":placeholder",
     ":recommend_apps",
     ":remote_activity_notification",
@@ -196,18 +191,6 @@
   ]
 }
 
-js_library("cryptohome_recovery_setup") {
-  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/cryptohome_recovery_setup.js" ]
-  deps = [
-    "../../components/behaviors:login_screen_behavior",
-    "../../components/behaviors:multi_step_behavior",
-    "../../components/behaviors:oobe_i18n_behavior",
-    "../../components/dialogs:oobe_adaptive_dialog",
-    "../../components/dialogs:oobe_loading_dialog",
-  ]
-  extra_deps = [ ":web_components" ]
-}
-
 js_library("device_disabled") {
   sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/device_disabled.js" ]
   deps = [
@@ -275,26 +258,6 @@
   extra_deps = [ ":web_components" ]
 }
 
-js_library("fingerprint_setup") {
-  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/fingerprint_setup.js" ]
-  deps = [
-    "../../components:display_manager_types",
-    "../../components:oobe_cr_lottie",
-    "../../components/behaviors:login_screen_behavior",
-    "../../components/behaviors:multi_step_behavior",
-    "../../components/behaviors:oobe_i18n_behavior",
-    "../../components/buttons:oobe_text_button",
-    "../../components/dialogs:oobe_adaptive_dialog",
-    "//ash/webui/common/resources:load_time_data.m",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-  ]
-  externs_list = [
-    "//ash/webui/common/resources/quick_unlock/fingerprint_progress_externs.js",
-  ]
-
-  extra_deps = [ ":web_components" ]
-}
-
 js_library("gesture_navigation") {
   sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/gesture_navigation.js" ]
   deps = [
@@ -366,21 +329,6 @@
   extra_deps = [ ":web_components" ]
 }
 
-js_library("local_password_setup") {
-  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/local_password_setup.js" ]
-  deps = [
-    "../../components/behaviors:login_screen_behavior",
-    "../../components/behaviors:multi_step_behavior",
-    "../../components/behaviors:oobe_dialog_host_behavior",
-    "../../components/behaviors:oobe_i18n_behavior",
-    "../../components/buttons:oobe_back_button",
-    "../../components/buttons:oobe_next_button",
-    "../../components/dialogs:oobe_adaptive_dialog",
-    "../../components/dialogs:oobe_loading_dialog",
-  ]
-  extra_deps = [ ":web_components" ]
-}
-
 js_library("local_state_error") {
   sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/local_state_error.js" ]
   deps = [
@@ -542,46 +490,6 @@
   extra_deps = [ ":web_components" ]
 }
 
-js_library("pin_setup") {
-  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/pin_setup.js" ]
-  deps = [
-    "../../components:oobe_types",
-    "../../components/behaviors:login_screen_behavior",
-    "../../components/behaviors:multi_step_behavior",
-    "../../components/behaviors:oobe_dialog_host_behavior",
-    "../../components/behaviors:oobe_i18n_behavior",
-    "../../components/buttons:oobe_back_button",
-    "../../components/buttons:oobe_next_button",
-    "../../components/buttons:oobe_text_button",
-    "../../components/dialogs:oobe_adaptive_dialog",
-    "//ash/webui/common/resources:cr.m",
-  ]
-  extra_deps = [ ":web_components" ]
-  externs_list = [
-    "$externs_path/quick_unlock_private.js",
-
-    # setup_pin_keyboard_externs.js is a temporary band-aid to let this
-    # closure-compiled JS library depend on the typescript file
-    # setup_pin_keyboard.ts. If you remove this dependency, consider deleting
-    # the externs file if it's not used elsewhere.
-    "//ash/webui/common/resources/quick_unlock/setup_pin_keyboard_externs.js",
-  ]
-  extra_sources = [ "$interfaces_path/quick_unlock_private_interface.js" ]
-}
-
-js_library("password_selection") {
-  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/password_selection.js" ]
-  deps = [
-    "../../components/behaviors:login_screen_behavior",
-    "../../components/behaviors:oobe_dialog_host_behavior",
-    "../../components/behaviors:oobe_i18n_behavior",
-    "../../components/buttons:oobe_back_button",
-    "../../components/buttons:oobe_next_button",
-    "../../components/dialogs:oobe_adaptive_dialog",
-  ]
-  extra_deps = [ ":web_components" ]
-}
-
 js_library("gaia_info") {
   sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/gaia_info.js" ]
   deps = [
@@ -783,8 +691,6 @@
   js_files = [
     "adb_sideloading.js",
     "add_child.js",
-    "password_selection.js",
-    "cryptohome_recovery_setup.js",
     "app_downloading.js",
     "app_launch_splash.js",
     "assistant_optin.js",
@@ -797,13 +703,11 @@
     "enable_kiosk.js",
     "error_message.js",
     "family_link_notice.js",
-    "fingerprint_setup.js",
     "gaia_info.js",
     "gaia_signin.js",
     "gesture_navigation.js",
     "guest_tos.js",
     "hw_data_collection.js",
-    "local_password_setup.js",
     "local_state_error.js",
     "managed_terms_of_service.js",
     "marketing_opt_in.js",
@@ -814,7 +718,6 @@
     "os_install.js",
     "os_trial.js",
     "parental_handoff.js",
-    "pin_setup.js",
     "placeholder.js",
     "recommend_apps.js",
     "remote_activity_notification.js",
diff --git a/chrome/browser/resources/chromeos/login/screens/osauth/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/osauth/BUILD.gn
index c2ff67a..7973fc2 100644
--- a/chrome/browser/resources/chromeos/login/screens/osauth/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/screens/osauth/BUILD.gn
@@ -4,9 +4,113 @@
 
 import("//chrome/common/features.gni")
 import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/html_to_js.gni")
 
 js_type_check("closure_compile") {
   is_polymer3 = true
   closure_flags = default_closure_args
-  deps = []
+  deps = [
+    ":cryptohome_recovery_setup",
+    ":fingerprint_setup",
+    ":local_password_setup",
+    ":password_selection",
+    ":pin_setup",
+  ]
+}
+
+js_library("cryptohome_recovery_setup") {
+  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/osauth/cryptohome_recovery_setup.js" ]
+  deps = [
+    "../../components/behaviors:login_screen_behavior",
+    "../../components/behaviors:multi_step_behavior",
+    "../../components/behaviors:oobe_i18n_behavior",
+    "../../components/dialogs:oobe_adaptive_dialog",
+    "../../components/dialogs:oobe_loading_dialog",
+  ]
+  extra_deps = [ ":web_components" ]
+}
+
+js_library("fingerprint_setup") {
+  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/osauth/fingerprint_setup.js" ]
+  deps = [
+    "../../components:display_manager_types",
+    "../../components:oobe_cr_lottie",
+    "../../components/behaviors:login_screen_behavior",
+    "../../components/behaviors:multi_step_behavior",
+    "../../components/behaviors:oobe_i18n_behavior",
+    "../../components/buttons:oobe_text_button",
+    "../../components/dialogs:oobe_adaptive_dialog",
+    "//ash/webui/common/resources:load_time_data.m",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+  externs_list = [
+    "//ash/webui/common/resources/quick_unlock/fingerprint_progress_externs.js",
+  ]
+
+  extra_deps = [ ":web_components" ]
+}
+
+js_library("local_password_setup") {
+  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/osauth/local_password_setup.js" ]
+  deps = [
+    "../../components/behaviors:login_screen_behavior",
+    "../../components/behaviors:multi_step_behavior",
+    "../../components/behaviors:oobe_dialog_host_behavior",
+    "../../components/behaviors:oobe_i18n_behavior",
+    "../../components/buttons:oobe_back_button",
+    "../../components/buttons:oobe_next_button",
+    "../../components/dialogs:oobe_adaptive_dialog",
+    "../../components/dialogs:oobe_loading_dialog",
+  ]
+  extra_deps = [ ":web_components" ]
+}
+
+js_library("password_selection") {
+  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/osauth/password_selection.js" ]
+  deps = [
+    "../../components/behaviors:login_screen_behavior",
+    "../../components/behaviors:oobe_dialog_host_behavior",
+    "../../components/behaviors:oobe_i18n_behavior",
+    "../../components/buttons:oobe_back_button",
+    "../../components/buttons:oobe_next_button",
+    "../../components/dialogs:oobe_adaptive_dialog",
+  ]
+  extra_deps = [ ":web_components" ]
+}
+
+js_library("pin_setup") {
+  sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/osauth/pin_setup.js" ]
+  deps = [
+    "../../components:oobe_types",
+    "../../components/behaviors:login_screen_behavior",
+    "../../components/behaviors:multi_step_behavior",
+    "../../components/behaviors:oobe_dialog_host_behavior",
+    "../../components/behaviors:oobe_i18n_behavior",
+    "../../components/buttons:oobe_back_button",
+    "../../components/buttons:oobe_next_button",
+    "../../components/buttons:oobe_text_button",
+    "../../components/dialogs:oobe_adaptive_dialog",
+    "//ash/webui/common/resources:cr.m",
+  ]
+  extra_deps = [ ":web_components" ]
+  externs_list = [
+    "$externs_path/quick_unlock_private.js",
+
+    # setup_pin_keyboard_externs.js is a temporary band-aid to let this
+    # closure-compiled JS library depend on the typescript file
+    # setup_pin_keyboard.ts. If you remove this dependency, consider deleting
+    # the externs file if it's not used elsewhere.
+    "//ash/webui/common/resources/quick_unlock/setup_pin_keyboard_externs.js",
+  ]
+  extra_sources = [ "$interfaces_path/quick_unlock_private_interface.js" ]
+}
+
+html_to_js("web_components") {
+  js_files = [
+    "cryptohome_recovery_setup.js",
+    "fingerprint_setup.js",
+    "local_password_setup.js",
+    "password_selection.js",
+    "pin_setup.js",
+  ]
 }
diff --git a/chrome/browser/resources/chromeos/login/screens/common/cryptohome_recovery_setup.html b/chrome/browser/resources/chromeos/login/screens/osauth/cryptohome_recovery_setup.html
similarity index 100%
rename from chrome/browser/resources/chromeos/login/screens/common/cryptohome_recovery_setup.html
rename to chrome/browser/resources/chromeos/login/screens/osauth/cryptohome_recovery_setup.html
diff --git a/chrome/browser/resources/chromeos/login/screens/common/cryptohome_recovery_setup.js b/chrome/browser/resources/chromeos/login/screens/osauth/cryptohome_recovery_setup.js
similarity index 100%
rename from chrome/browser/resources/chromeos/login/screens/common/cryptohome_recovery_setup.js
rename to chrome/browser/resources/chromeos/login/screens/osauth/cryptohome_recovery_setup.js
diff --git a/chrome/browser/resources/chromeos/login/screens/common/fingerprint_setup.html b/chrome/browser/resources/chromeos/login/screens/osauth/fingerprint_setup.html
similarity index 100%
rename from chrome/browser/resources/chromeos/login/screens/common/fingerprint_setup.html
rename to chrome/browser/resources/chromeos/login/screens/osauth/fingerprint_setup.html
diff --git a/chrome/browser/resources/chromeos/login/screens/common/fingerprint_setup.js b/chrome/browser/resources/chromeos/login/screens/osauth/fingerprint_setup.js
similarity index 100%
rename from chrome/browser/resources/chromeos/login/screens/common/fingerprint_setup.js
rename to chrome/browser/resources/chromeos/login/screens/osauth/fingerprint_setup.js
diff --git a/chrome/browser/resources/chromeos/login/screens/common/local_password_setup.html b/chrome/browser/resources/chromeos/login/screens/osauth/local_password_setup.html
similarity index 100%
rename from chrome/browser/resources/chromeos/login/screens/common/local_password_setup.html
rename to chrome/browser/resources/chromeos/login/screens/osauth/local_password_setup.html
diff --git a/chrome/browser/resources/chromeos/login/screens/common/local_password_setup.js b/chrome/browser/resources/chromeos/login/screens/osauth/local_password_setup.js
similarity index 100%
rename from chrome/browser/resources/chromeos/login/screens/common/local_password_setup.js
rename to chrome/browser/resources/chromeos/login/screens/osauth/local_password_setup.js
diff --git a/chrome/browser/resources/chromeos/login/screens/common/password_selection.html b/chrome/browser/resources/chromeos/login/screens/osauth/password_selection.html
similarity index 100%
rename from chrome/browser/resources/chromeos/login/screens/common/password_selection.html
rename to chrome/browser/resources/chromeos/login/screens/osauth/password_selection.html
diff --git a/chrome/browser/resources/chromeos/login/screens/common/password_selection.js b/chrome/browser/resources/chromeos/login/screens/osauth/password_selection.js
similarity index 100%
rename from chrome/browser/resources/chromeos/login/screens/common/password_selection.js
rename to chrome/browser/resources/chromeos/login/screens/osauth/password_selection.js
diff --git a/chrome/browser/resources/chromeos/login/screens/common/pin_setup.html b/chrome/browser/resources/chromeos/login/screens/osauth/pin_setup.html
similarity index 100%
rename from chrome/browser/resources/chromeos/login/screens/common/pin_setup.html
rename to chrome/browser/resources/chromeos/login/screens/osauth/pin_setup.html
diff --git a/chrome/browser/resources/chromeos/login/screens/common/pin_setup.js b/chrome/browser/resources/chromeos/login/screens/osauth/pin_setup.js
similarity index 100%
rename from chrome/browser/resources/chromeos/login/screens/common/pin_setup.js
rename to chrome/browser/resources/chromeos/login/screens/osauth/pin_setup.js
diff --git a/chrome/browser/resources/chromeos/notification_tester/BUILD.gn b/chrome/browser/resources/chromeos/notification_tester/BUILD.gn
index fcb1496..f82b580 100644
--- a/chrome/browser/resources/chromeos/notification_tester/BUILD.gn
+++ b/chrome/browser/resources/chromeos/notification_tester/BUILD.gn
@@ -67,7 +67,10 @@
     ":types",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
   ]
-  externs_list = [ "$externs_path/chrome_send.js" ]
+  externs_list = [
+    "$externs_path/chrome_send.js",
+    "$externs_path/pending.js",
+  ]
 }
 
 js_library("select_custom") {
diff --git a/chrome/browser/resources/chromeos/notification_tester/notification_tester.js b/chrome/browser/resources/chromeos/notification_tester/notification_tester.js
index 9eb41cd..7e703f1 100644
--- a/chrome/browser/resources/chromeos/notification_tester/notification_tester.js
+++ b/chrome/browser/resources/chromeos/notification_tester/notification_tester.js
@@ -212,8 +212,7 @@
         this.notificationDelayTime = '';
         // Create a deep copy of the current state of this.notifMetadata to
         // ensure it won't be modified before chrome.send() is called.
-        const notifMetadataCopy =
-            JSON.parse(JSON.stringify(this.notifMetadata));
+        const notifMetadataCopy = structuredClone(this.notifMetadata);
         setTimeout(
             chrome.send, timedInputValueNumber * NUM_MS_IN_S,
             'generateNotificationForm', [notifMetadataCopy]);
diff --git a/chrome/browser/resources/compose/app.html b/chrome/browser/resources/compose/app.html
index 3e67225d..2ad5ee5 100644
--- a/chrome/browser/resources/compose/app.html
+++ b/chrome/browser/resources/compose/app.html
@@ -40,10 +40,15 @@
   }
 
   cr-icon-button {
+    --cr-icon-button-fill-color: var(--cr-secondary-text-color);
     margin: 0;
     margin-inline-end: -6px;
   }
 
+  :host-context([chrome-refresh-2023]) cr-icon-button {
+    --cr-icon-button-fill-color: var(--color-compose-dialog-foreground-subtle);
+  }
+
   #bodyAndFooter {
     display: flex;
     flex-direction: column;
@@ -283,7 +288,7 @@
               on-click="onUndoClick_">
           </cr-icon-button>
           <cr-icon-button id="refreshButton" iron-icon="compose:refresh"
-              on-click="onSubmit_">
+              on-click="onRefresh_">
           </cr-icon-button>
         </div>
       </div>
diff --git a/chrome/browser/resources/compose/app.ts b/chrome/browser/resources/compose/app.ts
index c41172f9f..f24e92c3 100644
--- a/chrome/browser/resources/compose/app.ts
+++ b/chrome/browser/resources/compose/app.ts
@@ -16,6 +16,7 @@
 import {CrButtonElement} from '//resources/cr_elements/cr_button/cr_button.js';
 import {CrScrollableMixin} from '//resources/cr_elements/cr_scrollable_mixin.js';
 import {I18nMixin} from '//resources/cr_elements/i18n_mixin.js';
+import {assert} from '//resources/js/assert.js';
 import {EventTracker} from '//resources/js/event_tracker.js';
 import {loadTimeData} from '//resources/js/load_time_data.js';
 import {Debouncer, microTask, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -259,6 +260,14 @@
     this.isEditingSubmittedInput_ = true;
   }
 
+  private onRefresh_() {
+    assert(this.$.textarea.validate());
+    assert(this.submitted_);
+    this.selectedLength_ = Length.kUnset;
+    this.selectedTone_ = Tone.kUnset;
+    this.compose_();
+  }
+
   private onSubmit_() {
     if (!this.$.textarea.validate()) {
       return;
diff --git a/chrome/browser/resources/downloads/item.ts b/chrome/browser/resources/downloads/item.ts
index 4e8e938..c13773f1 100644
--- a/chrome/browser/resources/downloads/item.ts
+++ b/chrome/browser/resources/downloads/item.ts
@@ -468,8 +468,9 @@
       case State.kAsyncScanning:
         return loadTimeData.getString('asyncScanningDownloadDesc');
       case State.kPromptForScanning:
-      case State.kPromptForLocalPasswordScanning:  // Fallthrough.
         return loadTimeData.getString('promptForScanningDesc');
+      case State.kPromptForLocalPasswordScanning:
+        return loadTimeData.getString('promptForLocalPasswordScanningDesc');
       case State.kInProgress:
       case State.kPaused:  // Fallthrough.
         return data.progressStatusText;
diff --git a/chrome/browser/resources/history/app.ts b/chrome/browser/resources/history/app.ts
index 7d730c5..5a3913a 100644
--- a/chrome/browser/resources/history/app.ts
+++ b/chrome/browser/resources/history/app.ts
@@ -16,28 +16,31 @@
 import './side_bar.js';
 import './strings.m.js';
 
-import {CrDrawerElement} from 'chrome://resources/cr_elements/cr_drawer/cr_drawer.js';
-import {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.js';
-import {FindShortcutMixin, FindShortcutMixinInterface} from 'chrome://resources/cr_elements/find_shortcut_mixin.js';
-import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
+import type {CrDrawerElement} from 'chrome://resources/cr_elements/cr_drawer/cr_drawer.js';
+import type {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.js';
+import type {FindShortcutMixinInterface} from 'chrome://resources/cr_elements/find_shortcut_mixin.js';
+import {FindShortcutMixin} from 'chrome://resources/cr_elements/find_shortcut_mixin.js';
+import type {WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
+import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
 import {assert} from 'chrome://resources/js/assert.js';
 import {EventTracker} from 'chrome://resources/js/event_tracker.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {getTrustedScriptURL} from 'chrome://resources/js/static_types.js';
 import {hasKeyModifiers} from 'chrome://resources/js/util.js';
 import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
-import {IronPagesElement} from 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
+import type {IronPagesElement} from 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
 import {IronScrollTargetBehavior} from 'chrome://resources/polymer/v3_0/iron-scroll-target-behavior/iron-scroll-target-behavior.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getTemplate} from './app.html.js';
-import {BrowserService, BrowserServiceImpl} from './browser_service.js';
+import type {BrowserService} from './browser_service.js';
+import {BrowserServiceImpl} from './browser_service.js';
 import {HistoryPageViewHistogram} from './constants.js';
-import {ForeignSession, QueryResult, QueryState} from './externs.js';
-import {HistoryListElement} from './history_list.js';
-import {HistoryToolbarElement} from './history_toolbar.js';
+import type {ForeignSession, QueryResult, QueryState} from './externs.js';
+import type {HistoryListElement} from './history_list.js';
+import type {HistoryToolbarElement} from './history_toolbar.js';
 import {Page, TABBED_PAGES} from './router.js';
-import {FooterInfo, HistorySideBarElement} from './side_bar.js';
+import type {FooterInfo, HistorySideBarElement} from './side_bar.js';
 
 let lazyLoadPromise: Promise<void>|null = null;
 export function ensureLazyLoaded(): Promise<void> {
diff --git a/chrome/browser/resources/history/browser_service.ts b/chrome/browser/resources/history/browser_service.ts
index 7f91debc..4d10107 100644
--- a/chrome/browser/resources/history/browser_service.ts
+++ b/chrome/browser/resources/history/browser_service.ts
@@ -3,8 +3,9 @@
 // found in the LICENSE file.
 
 import {sendWithPromise} from 'chrome://resources/js/cr.js';
+
 import {RESULTS_PER_PAGE} from './constants.js';
-import {ForeignSession, HistoryEntry, HistoryQuery} from './externs.js';
+import type {ForeignSession, HistoryEntry, HistoryQuery} from './externs.js';
 
 export type RemoveVisitsRequest = Array<{
   url: string,
diff --git a/chrome/browser/resources/history/history_item.ts b/chrome/browser/resources/history/history_item.ts
index 30dd315..f618a26 100644
--- a/chrome/browser/resources/history/history_item.ts
+++ b/chrome/browser/resources/history/history_item.ts
@@ -10,8 +10,8 @@
 import 'chrome://resources/js/icon.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 
-import {CrCheckboxElement} from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js';
-import {CrIconButtonElement} from 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
+import type {CrCheckboxElement} from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js';
+import type {CrIconButtonElement} from 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
 import {FocusRowMixin} from 'chrome://resources/cr_elements/focus_row_mixin.js';
 import {EventTracker} from 'chrome://resources/js/event_tracker.js';
 import {focusWithoutInk} from 'chrome://resources/js/focus_without_ink.js';
@@ -20,7 +20,7 @@
 import {afterNextRender, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {BrowserServiceImpl} from './browser_service.js';
-import {HistoryEntry} from './externs.js';
+import type {HistoryEntry} from './externs.js';
 import {getTemplate} from './history_item.html.js';
 
 export interface HistoryItemElement {
diff --git a/chrome/browser/resources/history/history_list.ts b/chrome/browser/resources/history/history_list.ts
index f04dd21d..5b87fb6 100644
--- a/chrome/browser/resources/history/history_list.ts
+++ b/chrome/browser/resources/history/history_list.ts
@@ -10,22 +10,23 @@
 import './history_item.js';
 
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
-import {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
-import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
-import {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.js';
+import type {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
+import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
+import type {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
 import {assert} from 'chrome://resources/js/assert.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {getDeepActiveElement} from 'chrome://resources/js/util.js';
-import {IronListElement} from 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
-import {IronScrollThresholdElement} from 'chrome://resources/polymer/v3_0/iron-scroll-threshold/iron-scroll-threshold.js';
+import type {IronListElement} from 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
+import type {IronScrollThresholdElement} from 'chrome://resources/polymer/v3_0/iron-scroll-threshold/iron-scroll-threshold.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {BrowserServiceImpl} from './browser_service.js';
 import {BROWSING_GAP_TIME} from './constants.js';
-import {HistoryEntry, HistoryQuery, QueryState} from './externs.js';
-import {HistoryItemElement, searchResultsTitle} from './history_item.js';
+import type {HistoryEntry, HistoryQuery, QueryState} from './externs.js';
+import type {HistoryItemElement} from './history_item.js';
+import {searchResultsTitle} from './history_item.js';
 import {getTemplate} from './history_list.html.js';
 
 export interface ActionMenuModel {
diff --git a/chrome/browser/resources/history/history_toolbar.ts b/chrome/browser/resources/history/history_toolbar.ts
index 64875bf..f2210111 100644
--- a/chrome/browser/resources/history/history_toolbar.ts
+++ b/chrome/browser/resources/history/history_toolbar.ts
@@ -7,8 +7,8 @@
 import 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar.js';
 import 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.js';
 
-import {CrToolbarElement} from 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar.js';
-import {CrToolbarSearchFieldElement} from 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js';
+import type {CrToolbarElement} from 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar.js';
+import type {CrToolbarSearchFieldElement} from 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/history/query_manager.ts b/chrome/browser/resources/history/query_manager.ts
index ce025e3..49cbd44 100644
--- a/chrome/browser/resources/history/query_manager.ts
+++ b/chrome/browser/resources/history/query_manager.ts
@@ -6,9 +6,8 @@
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {BrowserServiceImpl} from './browser_service.js';
-import {HistoryEntry, HistoryQuery, QueryResult} from './externs.js';
-import {QueryState} from './externs.js';
-import {HistoryRouterElement} from './router.js';
+import type {HistoryEntry, HistoryQuery, QueryResult, QueryState} from './externs.js';
+import type {HistoryRouterElement} from './router.js';
 
 declare global {
   interface HTMLElementTagNameMap {
diff --git a/chrome/browser/resources/history/router.ts b/chrome/browser/resources/history/router.ts
index 3e35de7..5ebdf66 100644
--- a/chrome/browser/resources/history/router.ts
+++ b/chrome/browser/resources/history/router.ts
@@ -8,7 +8,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {Debouncer, microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {QueryState} from './externs.js';
+import type {QueryState} from './externs.js';
 import {getTemplate} from './router.html.js';
 
 // All valid pages.
diff --git a/chrome/browser/resources/history/side_bar.ts b/chrome/browser/resources/history/side_bar.ts
index cc0e3c9..564a884 100644
--- a/chrome/browser/resources/history/side_bar.ts
+++ b/chrome/browser/resources/history/side_bar.ts
@@ -18,9 +18,9 @@
 
 import {BrowserProxyImpl} from 'chrome://resources/cr_components/history_clusters/browser_proxy.js';
 import {MetricsProxyImpl} from 'chrome://resources/cr_components/history_clusters/metrics_proxy.js';
-import {CrMenuSelector} from 'chrome://resources/cr_elements/cr_menu_selector/cr_menu_selector.js';
+import type {CrMenuSelector} from 'chrome://resources/cr_elements/cr_menu_selector/cr_menu_selector.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
-import {PaperRippleElement} from 'chrome://resources/polymer/v3_0/paper-ripple/paper-ripple.js';
+import type {PaperRippleElement} from 'chrome://resources/polymer/v3_0/paper-ripple/paper-ripple.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {BrowserServiceImpl} from './browser_service.js';
diff --git a/chrome/browser/resources/history/synced_device_card.ts b/chrome/browser/resources/history/synced_device_card.ts
index 8fdf646..9001a435 100644
--- a/chrome/browser/resources/history/synced_device_card.ts
+++ b/chrome/browser/resources/history/synced_device_card.ts
@@ -14,12 +14,12 @@
 import {FocusRow} from 'chrome://resources/js/focus_row.js';
 import {getFaviconForPageURL} from 'chrome://resources/js/icon.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
-import {IronCollapseElement} from 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
+import type {IronCollapseElement} from 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {BrowserServiceImpl} from './browser_service.js';
 import {SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram} from './constants.js';
-import {ForeignSessionTab} from './externs.js';
+import type {ForeignSessionTab} from './externs.js';
 import {getTemplate} from './synced_device_card.html.js';
 
 interface OpenTabEvent {
diff --git a/chrome/browser/resources/history/synced_device_manager.ts b/chrome/browser/resources/history/synced_device_manager.ts
index 4bf3bf4..12eb26a 100644
--- a/chrome/browser/resources/history/synced_device_manager.ts
+++ b/chrome/browser/resources/history/synced_device_manager.ts
@@ -12,18 +12,18 @@
 import './synced_device_card.js';
 import './strings.m.js';
 
-import {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
-import {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.js';
+import type {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
+import type {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.js';
 import {assert} from 'chrome://resources/js/assert.js';
 import {FocusGrid} from 'chrome://resources/js/focus_grid.js';
-import {FocusRow} from 'chrome://resources/js/focus_row.js';
+import type {FocusRow} from 'chrome://resources/js/focus_row.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {Debouncer, microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {BrowserServiceImpl} from './browser_service.js';
 import {SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram} from './constants.js';
-import {ForeignSession, ForeignSessionTab} from './externs.js';
-import {HistorySyncedDeviceCardElement} from './synced_device_card.js';
+import type {ForeignSession, ForeignSessionTab} from './externs.js';
+import type {HistorySyncedDeviceCardElement} from './synced_device_card.js';
 import {getTemplate} from './synced_device_manager.html.js';
 
 interface ForeignDeviceInternal {
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/history_clusters/header_tile.html b/chrome/browser/resources/new_tab_page/modules/v2/history_clusters/header_tile.html
index dd3d70c..b0cf096 100644
--- a/chrome/browser/resources/new_tab_page/modules/v2/history_clusters/header_tile.html
+++ b/chrome/browser/resources/new_tab_page/modules/v2/history_clusters/header_tile.html
@@ -41,6 +41,10 @@
     width: 100%;
   }
 
+  ntp-module-header-v2 > cr-icon-button {
+    margin: 0;
+  }
+
   h2 {
     text-align: start;
   }
diff --git a/chrome/browser/resources/on_device_internals/app.ts b/chrome/browser/resources/on_device_internals/app.ts
index f8f92e1..d8dedc64 100644
--- a/chrome/browser/resources/on_device_internals/app.ts
+++ b/chrome/browser/resources/on_device_internals/app.ts
@@ -148,11 +148,13 @@
     // <if expr="not is_win">
     const processedPath = modelPath;
     // </if>
-    const {result} = await this.proxy_.handler.loadModel({path: processedPath});
-    if (result.error) {
-      this.error_ = result.error;
+    const newModel = new OnDeviceModelRemote();
+    const {error} = await this.proxy_.handler.loadModel(
+        {path: processedPath}, newModel.$.bindNewPipeAndPassReceiver());
+    if (error) {
+      this.error_ = error;
     } else {
-      this.model_ = result.model || null;
+      this.model_ = newModel;
       this.startNewSession_();
       this.modelPath_ = modelPath;
     }
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 22fdc428..017ee20 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -74,6 +74,7 @@
   web_component_files = [
     "a11y_page/a11y_page.ts",
     "about_page/about_page.ts",
+    "ai_page/ai_page.ts",
     "appearance_page/appearance_fonts_page.ts",
     "appearance_page/appearance_page.ts",
     "appearance_page/home_url_input.ts",
diff --git a/chrome/browser/resources/settings/ai_page/ai_page.html b/chrome/browser/resources/settings/ai_page/ai_page.html
new file mode 100644
index 0000000..bdc2135
--- /dev/null
+++ b/chrome/browser/resources/settings/ai_page/ai_page.html
@@ -0,0 +1,63 @@
+<style include="cr-shared-style settings-shared">
+  .list-frame {
+    padding-inline-end: 0;
+  }
+
+  .list-frame settings-toggle-button {
+    padding-inline-start: 0;
+  }
+</style>
+
+<settings-toggle-button
+    pref="{{prefs.optimization_guide.model_execution_main_toggle_setting_state}}"
+    numeric-unchecked-values="[[numericUncheckedValues_]]"
+    numeric-checked-value="[[featureOptInStateEnum_.ENABLED]]"
+    label="$i18n{experimentalAdvancedFeatureMainLabel}"
+    sub-label="$i18n{experimentalAdvancedFeatureMainSublabel}"
+    on-settings-boolean-control-change="onToggleChange_">
+</settings-toggle-button>
+
+<iron-collapse opened="[[isExpanded_(
+    prefs.optimization_guide.model_execution_main_toggle_setting_state.value)]]">
+  <div class="list-frame">
+    <settings-toggle-button
+        hidden="[[!showComposeControl_]]"
+        pref="{{prefs.optimization_guide.compose_setting_state}}"
+        numeric-unchecked-values="[[numericUncheckedValues_]]"
+        numeric-checked-value="[[featureOptInStateEnum_.ENABLED]]"
+        label="$i18n{experimentalAdvancedFeature1Label}"
+        sub-label="$i18n{experimentalAdvancedFeature1Sublabel}"
+        on-settings-boolean-control-change="onToggleChange_">
+    </settings-toggle-button>
+    <settings-toggle-button
+        hidden="[[!showTabOrganizationControl_]]"
+        pref="{{prefs.optimization_guide.tab_organization_setting_state}}"
+        numeric-unchecked-values="[[numericUncheckedValues_]]"
+        numeric-checked-value="[[featureOptInStateEnum_.ENABLED]]"
+        label="$i18n{experimentalAdvancedFeature2Label}"
+        sub-label="$i18n{experimentalAdvancedFeature2Sublabel}"
+        on-settings-boolean-control-change="onToggleChange_">
+    </settings-toggle-button>
+    <settings-toggle-button
+        hidden="[[!showWallpaperSearchControl_]]"
+        pref="{{prefs.optimization_guide.wallpaper_search_setting_state}}"
+        numeric-unchecked-values="[[numericUncheckedValues_]]"
+        numeric-checked-value="[[featureOptInStateEnum_.ENABLED]]"
+        label="$i18n{experimentalAdvancedFeature3Label}"
+        sub-label="$i18n{experimentalAdvancedFeature3Sublabel}"
+        on-settings-boolean-control-change="onToggleChange_">
+    </settings-toggle-button>
+  </div>
+</iron-collapse>
+
+<cr-toast id="toast">
+  <div>$i18n{restartToApplyChanges}</div>
+  <cr-button on-click="onRestartClick_">$i18n{restart}</cr-button>
+</cr-toast>
+
+<if expr="not chromeos_ash">
+<template is="dom-if" if="[[shouldShowRelaunchDialog]]" restamp>
+  <relaunch-confirmation-dialog restart-type="[[restartTypeEnum.RESTART]]"
+      on-close="onRelaunchDialogClose"></relaunch-confirmation-dialog>
+</template>
+</if>
diff --git a/chrome/browser/resources/settings/ai_page/ai_page.ts b/chrome/browser/resources/settings/ai_page/ai_page.ts
new file mode 100644
index 0000000..678eae5f
--- /dev/null
+++ b/chrome/browser/resources/settings/ai_page/ai_page.ts
@@ -0,0 +1,118 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import '/shared/settings/controls/settings_toggle_button.js';
+import 'chrome://resources/cr_elements/cr_button/cr_button.js';
+import 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
+import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
+// <if expr="not chromeos_ash">
+import '../relaunch_confirmation_dialog.js';
+
+// </if>
+
+import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
+import {CrToastElement} from 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
+import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {loadTimeData} from '../i18n_setup.js';
+import {RelaunchMixin, RestartType} from '../relaunch_mixin.js';
+
+import {getTemplate} from './ai_page.html.js';
+
+// These values must stay in sync with
+// optimization_guide::prefs::FeatureOptInState in
+// components/optimization_guide/core/optimization_guide_prefs.h.
+export enum FeatureOptInState {
+  NOT_INITIALIZED = 0,
+  ENABLED = 1,
+  DISABLED = 2,
+}
+
+// Exporting pref names so that they can be referenced by tests.
+export enum SettingsAiPageFeaturePrefName {
+  MAIN = 'optimization_guide.model_execution_main_toggle_setting_state',
+  COMPOSE = 'optimization_guide.compose_setting_state',
+  TAB_ORGANIZATION = 'optimization_guide.tab_organization_setting_state',
+  WALLPAPER_SEARCH = 'optimization_guide.wallpaper_search_setting_state',
+}
+
+export interface SettingsAiPageElement {
+  $: {
+    toast: CrToastElement,
+  };
+}
+
+const SettingsAiPageElementBase = RelaunchMixin(PrefsMixin(PolymerElement));
+
+export class SettingsAiPageElement extends SettingsAiPageElementBase {
+  static get is() {
+    return 'settings-ai-page';
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {
+      prefs: {
+        type: Object,
+        notify: true,
+      },
+
+      showComposeControl_: {
+        type: Boolean,
+        value: () => loadTimeData.getBoolean('showComposeControl'),
+      },
+
+      showTabOrganizationControl_: {
+        type: Boolean,
+        value: () => loadTimeData.getBoolean('showTabOrganizationControl'),
+      },
+
+      showWallpaperSearchControl_: {
+        type: Boolean,
+        value: () => loadTimeData.getBoolean('showWallpaperSearchControl'),
+      },
+
+      featureOptInStateEnum_: {
+        type: Object,
+        value: FeatureOptInState,
+      },
+
+      numericUncheckedValues_: {
+        type: Array,
+        value: () =>
+            [FeatureOptInState.DISABLED, FeatureOptInState.NOT_INITIALIZED],
+      },
+    };
+  }
+
+  private showComposeControl_: boolean;
+  private showTabOrganizationControl_: boolean;
+  private showWallpaperSearchControl_: boolean;
+  private numericUncheckedValues_: FeatureOptInState[];
+
+  private onToggleChange_() {
+    this.$.toast.show();
+  }
+
+  private onRestartClick_(e: Event) {
+    e.stopPropagation();
+    this.performRestart(RestartType.RESTART);
+  }
+
+  private isExpanded_(): boolean {
+    return this.getPref(SettingsAiPageFeaturePrefName.MAIN).value ===
+        FeatureOptInState.ENABLED;
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'settings-ai-page': SettingsAiPageElement;
+  }
+}
+
+customElements.define(SettingsAiPageElement.is, SettingsAiPageElement);
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html
index 957329a..0f55093 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -24,6 +24,14 @@
             </settings-people-page>
           </settings-section>
         </template>
+        <template is="dom-if"
+            if="[[showExperimentalAdvancedPage_(pageVisibility.ai)]]"
+            restamp>
+          <settings-section page-title="$i18n{experimentalAdvancedPageTitle}"
+              section="ai">
+            <settings-ai-page prefs="{{prefs}}"></settings-ai-page>
+          </settings-section>
+        </template>
         <template is="dom-if" if="[[showPage_(pageVisibility.autofill)]]"
             restamp>
           <settings-section page-title="$i18n{autofillPageTitle}"
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.ts b/chrome/browser/resources/settings/basic_page/basic_page.ts
index 489c236..9d78e58 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.ts
+++ b/chrome/browser/resources/settings/basic_page/basic_page.ts
@@ -10,6 +10,7 @@
 import 'chrome://resources/cr_elements/cr_shared_style.css.js';
 import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
 import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
+import '../ai_page/ai_page.js';
 import '../appearance_page/appearance_page.js';
 import '../privacy_page/preloading_page.js';
 import '../privacy_page/privacy_guide/privacy_guide_promo.js';
@@ -177,6 +178,11 @@
               'isPerformanceSettingsPreloadingSubpageV2Enabled');
         },
       },
+
+      showAdvancedFeaturesMainControl_: {
+        type: Boolean,
+        value: () => loadTimeData.getBoolean('showAdvancedFeaturesMainControl'),
+      },
     };
   }
 
@@ -199,6 +205,7 @@
   private currentRoute_: Route;
   private advancedTogglingInProgress_: boolean;
   private showBatterySettings_: boolean;
+  private showAdvancedFeaturesMainControl_: boolean;
 
   private showPrivacyGuidePromo_: boolean;
   private privacyGuidePromoWasShown_: boolean;
@@ -411,6 +418,11 @@
         this.showPage_(visibility);
   }
 
+  private showExperimentalAdvancedPage_(visibility?: boolean): boolean {
+    return loadTimeData.getBoolean('showAdvancedFeaturesMainControl') &&
+        this.showPage_(visibility);
+  }
+
   // <if expr="_google_chrome">
   private showGetMostChrome_(visibility?: boolean): boolean {
     return visibility !== false &&
diff --git a/chrome/browser/resources/settings/icons.html b/chrome/browser/resources/settings/icons.html
index 114d3ba8..b7b0174 100644
--- a/chrome/browser/resources/settings/icons.html
+++ b/chrome/browser/resources/settings/icons.html
@@ -148,9 +148,7 @@
       <g id="accessibility"><path d="M12 2c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 7h-6v13h-2v-6h-2v6H9V9H3V7h18v2z"></path></g>
       <g id="apps"><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"></path></g>
       <g id="assignment"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"></path></g>
-<if expr="not chromeos_ash">
       <g id="build"><path d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z"></path></g>
-</if>
       <g id="check-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"></path></g>
       <g id="clipboard"><path d="M19,3h-4.18C14.4,1.84,13.3,1,12,1S9.6,1.84,9.18,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5 C21,3.9,20.1,3,19,3z M12,3c0.55,0,1,0.45,1,1s-0.45,1-1,1s-1-0.45-1-1S11.45,3,12,3z M19,19H5V5h2v3h10V5h2V19z"></path></g>
       <g id="clipboard-off"><path d="M21.19,21.19L2.81,2.81L1.39,4.22L3,5.83V19c0,1.1,0.9,2,2,2h13.17l1.61,1.61L21.19,21.19z M5,19V7.83L16.17,19H5z M17,8V5 h2v11.17l2,2V5c0-1.1-0.9-2-2-2h-4.18C14.4,1.84,13.3,1,12,1S9.6,1.84,9.18,3H5.83l5,5H17z M12,3c0.55,0,1,0.45,1,1s-0.45,1-1,1 s-1-0.45-1-1S11.45,3,12,3z"></path></g>
diff --git a/chrome/browser/resources/settings/page_visibility.ts b/chrome/browser/resources/settings/page_visibility.ts
index b7a7bc8..06d225f2 100644
--- a/chrome/browser/resources/settings/page_visibility.ts
+++ b/chrome/browser/resources/settings/page_visibility.ts
@@ -10,6 +10,7 @@
 export interface PageVisibility {
   a11y?: boolean;
   advancedSettings?: boolean;
+  ai?: boolean;
   appearance?: boolean|AppearancePageVisibility;
   autofill?: boolean;
   defaultBrowser?: boolean;
@@ -53,6 +54,7 @@
   pageVisibility = {
     a11y: false,
     advancedSettings: false,
+    ai: false,
     appearance: false,
     autofill: false,
     defaultBrowser: false,
@@ -72,6 +74,7 @@
   // </if>
   // <if expr="is_chromeos">
   pageVisibility = {
+    ai: false,
     autofill: false,
     people: false,
     onStartup: false,
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index fcadba7..98b41c9 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -715,12 +715,13 @@
             </template>
             <template is="dom-if" if="[[showNotificationPermissionsReview_]]">
               <template is="dom-if" if="[[enableSafetyHub_]]">
+                <h2>$i18n{safetyHub}</h2>
                 <settings-safety-hub-module id="safetyHubEntryPoint"
                     header="[[notificationPermissionsReviewHeader_]]"
                     subheader="[[notificationPermissionsReviewSubheader_]]"
                     header-icon="cr:security" header-icon-color="blue">
                   <cr-button id="safetyHubButton" slot="button-container"
-                      on-click="onSafetyHubButtonClick_">
+                      class="action-button" on-click="onSafetyHubButtonClick_">
                     $i18n{safetyHubEntryPointButton}
                   </cr-button>
                 </settings-safety-hub-module>
diff --git a/chrome/browser/resources/settings/route.ts b/chrome/browser/resources/settings/route.ts
index 2bdbfd14..7f54089 100644
--- a/chrome/browser/resources/settings/route.ts
+++ b/chrome/browser/resources/settings/route.ts
@@ -175,6 +175,12 @@
 
   const visibility = pageVisibility || {};
 
+  if (visibility.ai !== false &&
+      loadTimeData.getBoolean('showAdvancedFeaturesMainControl')) {
+    r.AI = r.BASIC.createSection(
+        '/ai', 'ai', loadTimeData.getString('experimentalAdvancedPageTitle'));
+  }
+
   // <if expr="not chromeos_ash">
   if (visibility.people !== false) {
     assert(r.PEOPLE);
diff --git a/chrome/browser/resources/settings/router.ts b/chrome/browser/resources/settings/router.ts
index e92249b..3545090 100644
--- a/chrome/browser/resources/settings/router.ts
+++ b/chrome/browser/resources/settings/router.ts
@@ -16,6 +16,7 @@
   ACCESSIBILITY: Route;
   ADDRESSES: Route;
   ADVANCED: Route;
+  AI: Route;
   APPEARANCE: Route;
   AUTOFILL: Route;
   BASIC: Route;
diff --git a/chrome/browser/resources/settings/safety_hub/notification_permissions_module.html b/chrome/browser/resources/settings/safety_hub/notification_permissions_module.html
index 211cf15..b12d271e 100644
--- a/chrome/browser/resources/settings/safety_hub/notification_permissions_module.html
+++ b/chrome/browser/resources/settings/safety_hub/notification_permissions_module.html
@@ -1,7 +1,6 @@
 <style include="cr-shared-style settings-shared">
-  :host {
-    display: block;
-    padding: 0 var(--cr-section-padding);
+    paper-tooltip {
+    --paper-tooltip-min-width: max-content;
   }
 </style>
 <settings-safety-hub-module
@@ -28,7 +27,9 @@
         hidden$="[[shouldShowCompletionInfo_]]" title="$i18n{moreActions}">
     </cr-icon-button>
     <cr-icon-button id="bulkUndoButton" iron-icon="settings20:undo"
-        on-click="onUndoClick_" hidden$="[[!shouldShowCompletionInfo_]]">
+        on-click="onUndoClick_" hidden$="[[!shouldShowCompletionInfo_]]"
+        on-focus="showUndoTooltip_" on-mouseenter="showUndoTooltip_"
+        aria-label$="$i18n{safetyCheckNotificationPermissionReviewUndo}">>
     </cr-icon-button>
   </div>
 </settings-safety-hub-module>
@@ -55,3 +56,6 @@
     $i18n{safetyCheckNotificationPermissionReviewUndo}
   </cr-button>
 </cr-toast>
+<paper-tooltip fit-to-visible-bounds manual-mode position="top" offset="3">
+  $i18n{safetyCheckNotificationPermissionReviewUndo}
+</paper-tooltip>
diff --git a/chrome/browser/resources/settings/safety_hub/notification_permissions_module.ts b/chrome/browser/resources/settings/safety_hub/notification_permissions_module.ts
index c3c5904e..aa6f5274 100644
--- a/chrome/browser/resources/settings/safety_hub/notification_permissions_module.ts
+++ b/chrome/browser/resources/settings/safety_hub/notification_permissions_module.ts
@@ -13,6 +13,7 @@
 import 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.js';
+import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js';
 import '../settings_shared.css.js';
 import '../i18n_setup.js';
 import '../icons.html.js';
@@ -32,6 +33,7 @@
 import {Route, RouteObserverMixin, Router} from '../router.js';
 import {NotificationPermission, SafetyHubBrowserProxy, SafetyHubBrowserProxyImpl, SafetyHubEvent} from '../safety_hub/safety_hub_browser_proxy.js';
 import {SiteSettingsMixin} from '../site_settings/site_settings_mixin.js';
+import {TooltipMixin} from '../tooltip_mixin.js';
 
 import {getTemplate} from './notification_permissions_module.html.js';
 import {SettingsSafetyHubModuleElement, SiteInfo, SiteInfoWithTarget} from './safety_hub_module.js';
@@ -66,8 +68,8 @@
                                                  SiteInfo {}
 
 const SettingsSafetyHubNotificationPermissionsModuleElementBase =
-    WebUiListenerMixin(RouteObserverMixin(
-        BaseMixin(SiteSettingsMixin(I18nMixin(PolymerElement)))));
+    TooltipMixin(WebUiListenerMixin(RouteObserverMixin(
+        BaseMixin(SiteSettingsMixin(I18nMixin(PolymerElement))))));
 
 export class SettingsSafetyHubNotificationPermissionsModuleElement extends
     SettingsSafetyHubNotificationPermissionsModuleElementBase {
@@ -375,6 +377,13 @@
     return this.i18n(
         'safetyCheckNotificationPermissionReviewResetAriaLabel', origins[0]);
   }
+
+  private showUndoTooltip_(e: Event) {
+    e.stopPropagation();
+    const tooltip = this.shadowRoot!.querySelector('paper-tooltip');
+    assert(tooltip);
+    this.showTooltipAtTarget(tooltip, e.target!);
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/settings/safety_hub/safety_hub_card.html b/chrome/browser/resources/settings/safety_hub/safety_hub_card.html
index 0025d13c..a50ebc8 100644
--- a/chrome/browser/resources/settings/safety_hub/safety_hub_card.html
+++ b/chrome/browser/resources/settings/safety_hub/safety_hub_card.html
@@ -8,6 +8,7 @@
 
   #header {
     /* Should be 12px when html font-size is 16px */
+    font-weight: 500;
     font-size: 0.75rem;
     user-select: none;
   }
@@ -15,6 +16,7 @@
   #subheader {
     /* Should be 11px when html font-size is 16px */
     font-size: 0.6875rem;
+    line-height: 18px;
     user-select: none;
   }
 
diff --git a/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.html b/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.html
index 63d265b2..6edd36a 100644
--- a/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.html
+++ b/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.html
@@ -1,4 +1,7 @@
 <style include="cr-shared-style">
+   :host {
+    padding: 8px 16px;
+  }
 </style>
 
 <!-- TODO(1443466): Right-align button. -->
diff --git a/chrome/browser/resources/settings/safety_hub/safety_hub_module.html b/chrome/browser/resources/settings/safety_hub/safety_hub_module.html
index 305b3d7..9f78869 100644
--- a/chrome/browser/resources/settings/safety_hub/safety_hub_module.html
+++ b/chrome/browser/resources/settings/safety_hub/safety_hub_module.html
@@ -1,20 +1,21 @@
 <style include="cr-shared-style settings-shared">
   :host {
     display: block;
-    padding: 8px 16px;
 
     --separator-line-height: 16px;
+    --cr-icon-button-margin-end: 0;
   }
 
   #header-wrapper {
     align-items: center;
     display: flex;
+    flex: 1;
   }
 
   #header-text-wrapper {
     flex-direction: column;
     flex: 1;
-    margin-inline-end: 16px;
+    margin-inline-end: 24px;
   }
 
   #header, #subheader, .display-name {
@@ -56,8 +57,6 @@
   }
 
   .list-item {
-    --cr-icon-button-margin-end: initial;
-
     /**
      * As the animation decreases max-height of rows, it can push content out
      * of the bounding box of the item, which will appear as a quick flash
@@ -83,10 +82,6 @@
     flex: 1;
   }
 
-  .link a[href] {
-    text-decoration: none;
-  }
-
   paper-tooltip {
     --paper-tooltip-min-width: max-content;
   }
diff --git a/chrome/browser/resources/settings/safety_hub/safety_hub_page.html b/chrome/browser/resources/settings/safety_hub/safety_hub_page.html
index 555ab19..86e09a8 100644
--- a/chrome/browser/resources/settings/safety_hub/safety_hub_page.html
+++ b/chrome/browser/resources/settings/safety_hub/safety_hub_page.html
@@ -13,33 +13,40 @@
   .card-container {
     align-items: stretch;
     display: flex;
-    gap: 13px;
+    gap: 16px;
     justify-content: space-between;
     width: 100%;
   }
 
   .card:hover {
     background-color: var(--cr-hover-background-color);
+    cursor: pointer;
   }
 
   .module {
     height: fit-content;
-    margin-bottom: 24px;
+    margin-bottom: 16px;
+    padding: 12px 20px;
   }
 
   .section-header {
+    flex: 1;
     /* Should be 13px when html font-size is 16px */
     font-size: 0.8125rem;
-    margin: 16px 0px;
+    margin-bottom: 16px;
+    margin-top: 30px;
     width: 100%;
-    flex: 1;
     user-select: none;
   }
+
+  .section-header.first{
+    margin-top: 0px;
+  }
 </style>
 
-<div class="section-header cr-secondary-text">
+<h5 class="section-header cr-secondary-text first">
   $i18n{safetyHubPageCardSectionHeader}
-</div>
+</h5>
 <div class="card-container">
   <settings-safety-hub-card id="passwords" class="card box"
       data="[[passwordCardData_]]" on-click="onPasswordsClick_"
@@ -54,9 +61,9 @@
       tabindex="0" on-keydown="onSafeBrowsingKeyPress_">
   </settings-safety-hub-card>
 </div>
-<div class="section-header cr-secondary-text">
+<h5 class="section-header cr-secondary-text">
   $i18n{safetyHubPageModuleSectionHeader}
-</div>
+</h5>
 <template is="dom-if" if="[[showNotificationPermissions_]]">
   <settings-safety-hub-notification-permissions-module class="module box">
   </settings-safety-hub-notification-permissions-module>
diff --git a/chrome/browser/resources/settings/safety_hub/unused_site_permissions_module.html b/chrome/browser/resources/settings/safety_hub/unused_site_permissions_module.html
index bb453f4..7a5fc5d 100644
--- a/chrome/browser/resources/settings/safety_hub/unused_site_permissions_module.html
+++ b/chrome/browser/resources/settings/safety_hub/unused_site_permissions_module.html
@@ -1,7 +1,6 @@
 <style include="cr-shared-style settings-shared">
-  :host {
-    display: block;
-    padding: 0 var(--cr-section-padding);
+    paper-tooltip {
+    --paper-tooltip-min-width: max-content;
   }
 </style>
 <settings-safety-hub-module
@@ -25,7 +24,9 @@
         title="$i18n{moreActions}">
     </cr-icon-button>
     <cr-icon-button id="bulkUndoButton" iron-icon="settings20:undo"
-        on-click="onUndoClick_" hidden$="[[!shouldShowCompletionInfo_]]">
+        on-click="onUndoClick_" hidden$="[[!shouldShowCompletionInfo_]]"
+        on-focus="showUndoTooltip_" on-mouseenter="showUndoTooltip_"
+        aria-label$="$i18n{safetyCheckUnusedSitePermissionsUndoLabel}">
     </cr-icon-button>
   </div>
 </settings-safety-hub-module>
@@ -41,3 +42,6 @@
     $i18n{safetyHubGoSiteSettingsItem}
   </button>
 </cr-action-menu>
+<paper-tooltip fit-to-visible-bounds manual-mode position="top" offset="3">
+  $i18n{safetyCheckUnusedSitePermissionsUndoLabel}
+</paper-tooltip>
diff --git a/chrome/browser/resources/settings/safety_hub/unused_site_permissions_module.ts b/chrome/browser/resources/settings/safety_hub/unused_site_permissions_module.ts
index c660c37..63a4f2d7 100644
--- a/chrome/browser/resources/settings/safety_hub/unused_site_permissions_module.ts
+++ b/chrome/browser/resources/settings/safety_hub/unused_site_permissions_module.ts
@@ -4,6 +4,7 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
 import 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
+import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js';
 import '../i18n_setup.js';
 import '../icons.html.js';
 import './safety_hub_module.js';
@@ -23,6 +24,7 @@
 import {ContentSettingsTypes} from '../site_settings/constants.js';
 import {SiteSettingsMixin} from '../site_settings/site_settings_mixin.js';
 import {getLocalizationStringForContentType} from '../site_settings_page/site_settings_page_util.js';
+import {TooltipMixin} from '../tooltip_mixin.js';
 
 import {SafetyHubBrowserProxy, SafetyHubBrowserProxyImpl, SafetyHubEvent, UnusedSitePermissions} from './safety_hub_browser_proxy.js';
 import {SettingsSafetyHubModuleElement, SiteInfo} from './safety_hub_module.js';
@@ -55,8 +57,9 @@
   detail: string;
 }
 
-const SettingsSafetyHubUnusedSitePermissionsModuleElementBase = I18nMixin(
-    RouteObserverMixin(WebUiListenerMixin(SiteSettingsMixin(PolymerElement))));
+const SettingsSafetyHubUnusedSitePermissionsModuleElementBase =
+    TooltipMixin(I18nMixin(RouteObserverMixin(
+        WebUiListenerMixin(SiteSettingsMixin(PolymerElement)))));
 
 export class SettingsSafetyHubUnusedSitePermissionsModuleElement extends
     SettingsSafetyHubUnusedSitePermissionsModuleElementBase {
@@ -341,6 +344,16 @@
     this.toastText_ = text;
     this.$.undoToast.show();
   }
+
+  // TODO(crbug.com/1443466): Move common functionality between
+  // unused_site_permissions_module.ts and notification_permissions_module.ts to
+  // a util class.
+  private showUndoTooltip_(e: Event) {
+    e.stopPropagation();
+    const tooltip = this.shadowRoot!.querySelector('paper-tooltip');
+    assert(tooltip);
+    this.showTooltipAtTarget(tooltip, e.target!);
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/settings/settings.ts b/chrome/browser/resources/settings/settings.ts
index 041e6116..57161ea2 100644
--- a/chrome/browser/resources/settings/settings.ts
+++ b/chrome/browser/resources/settings/settings.ts
@@ -44,6 +44,7 @@
 // </if>
 // clang-format on
 
+export {FeatureOptInState, SettingsAiPageElement, SettingsAiPageFeaturePrefName} from './ai_page/ai_page.js';
 export {AppearanceBrowserProxy, AppearanceBrowserProxyImpl} from './appearance_page/appearance_browser_proxy.js';
 export {SettingsAppearancePageElement, SystemTheme} from './appearance_page/appearance_page.js';
 export {HomeUrlInputElement} from './appearance_page/home_url_input.js';
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html
index 3b16ef0..9569bd3 100644
--- a/chrome/browser/resources/settings/settings_menu/settings_menu.html
+++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -90,6 +90,14 @@
           $i18n{performancePageTitle}
           <paper-ripple></paper-ripple>
         </a>
+        <a role="menuitem" href="/ai"
+            hidden="[[!showExperimentalMenuItem_(
+                showAdvancedFeaturesMainControl_, pageVisibility.ai)]]"
+            class="cr-nav-menu-item">
+          <iron-icon icon="settings:build"></iron-icon>
+          $i18n{experimentalAdvancedPageTitle}
+          <paper-ripple></paper-ripple>
+        </a>
         <a role="menuitem" id="appearance" href="/appearance"
             hidden="[[!pageVisibility.appearance]]"
             class="cr-nav-menu-item">
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.ts b/chrome/browser/resources/settings/settings_menu/settings_menu.ts
index 2134449a..736060a 100644
--- a/chrome/browser/resources/settings/settings_menu/settings_menu.ts
+++ b/chrome/browser/resources/settings/settings_menu/settings_menu.ts
@@ -52,10 +52,16 @@
        * Dictionary defining page visibility.
        */
       pageVisibility: Object,
+
+      showAdvancedFeaturesMainControl_: {
+        type: Boolean,
+        value: () => loadTimeData.getBoolean('showAdvancedFeaturesMainControl'),
+      },
     };
   }
 
   pageVisibility: PageVisibility;
+  private showAdvancedFeaturesMainControl_: boolean;
   private routes_: SettingsRoutes;
 
   override ready() {
@@ -63,6 +69,11 @@
     this.routes_ = Router.getInstance().getRoutes();
   }
 
+  private showExperimentalMenuItem_(): boolean {
+    return this.showAdvancedFeaturesMainControl_ &&
+        (!this.pageVisibility || this.pageVisibility.ai !== false);
+  }
+
   override currentRouteChanged(newRoute: Route) {
     // <if expr="_google_chrome">
     if (loadTimeData.getBoolean('showGetTheMostOutOfChromeSection') &&
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
index 82a6980..ac6ac864 100644
--- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
@@ -6,6 +6,10 @@
       img {
         width: 100%;
       }
+
+      #safetyHubModule {
+        padding: 0 var(--cr-section-padding);
+      }
     </style>
     <picture>
       <source
@@ -16,12 +20,15 @@
     </picture>
     <template is="dom-if" if="[[showUnusedSitePermissions_]]">
       <template is="dom-if" if="[[enableSafetyHub_]]">
+        <div class="cr-row first">
+          <h2>$i18n{safetyHub}</h2>
+        </div>
         <settings-safety-hub-module id="safetyHubModule"
             header="[[unusedSitePermissionsHeader_]]"
             subheader="[[unusedSitePermissionsSubheader_]]"
             header-icon="cr:security" header-icon-color="blue">
           <cr-button id="safetyHubButton" slot="button-container"
-              on-click="onSafetyHubButtonClick_">
+              class="action-button" on-click="onSafetyHubButtonClick_">
             $i18n{safetyHubEntryPointButton}
           </cr-button>
         </settings-safety-hub-module>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/wallpaper_search/wallpaper_search.html b/chrome/browser/resources/side_panel/customize_chrome/wallpaper_search/wallpaper_search.html
index 7635f24..0d62327 100644
--- a/chrome/browser/resources/side_panel/customize_chrome/wallpaper_search/wallpaper_search.html
+++ b/chrome/browser/resources/side_panel/customize_chrome/wallpaper_search/wallpaper_search.html
@@ -15,6 +15,36 @@
     position: relative;
   }
 
+  #error {
+    height: 100px;
+    line-height: 20px;
+    width: 272px;
+  }
+
+  #errorTitle {
+    font-size: 14px;
+    font-weight: 500;
+    color: var(--color-side-panel-card-primary-foreground);
+    margin-block-end: 8px;
+  }
+
+  #errorDescription {
+    color: var(--color-side-panel-card-secondary-foreground);
+    font-size: 13px;
+    margin-block-end: 16px;
+  }
+
+  #errorCTA {
+    background-color: var(
+        --color-side-panel-wallpaper-search-error-button-background);
+    border-color: var(
+        --color-side-panel-wallpaper-search-error-button-background);
+    color: var(
+        --color-side-panel-wallpaper-search-error-button-text);
+    float: right;
+    min-width: auto;
+  }
+
   customize-chrome-combobox {
     color: var(--color-side-panel-card-primary-foreground);
     font-size: 12px;
@@ -140,7 +170,7 @@
 
   .tile {
     background-color: var(
-        --color-side-panel-customize-chrome-wallpaper-search-tile-background);
+        --color-side-panel-wallpaper-search-tile-background);
     outline-width: 0;
     place-self: stretch;
   }
@@ -203,8 +233,11 @@
     <h2 slot="heading">$i18n{wallpaperSearchHeader}</h2>
   </sp-heading>
   <div class="content" id="error" hidden$="[[!errorState_]]">
-    <div>[[errorState_.title]]</div>
-    <div>[[errorState_.description]]</div>
+    <div id="errorTitle">[[errorState_.title]]</div>
+    <div id="errorDescription">[[errorState_.description]]</div>
+    <cr-button id="errorCTA" on-click="onErrorClick_">
+      [[errorState_.callToAction]]
+    </cr-button>
   </div>
   <div class="content" id="wallpaperSearch" hidden$="[[errorState_]]">
     <customize-chrome-combobox id="descriptorComboboxA" label="Descriptor A"
diff --git a/chrome/browser/resources/side_panel/customize_chrome/wallpaper_search/wallpaper_search.ts b/chrome/browser/resources/side_panel/customize_chrome/wallpaper_search/wallpaper_search.ts
index 8aaf67b..582481fd 100644
--- a/chrome/browser/resources/side_panel/customize_chrome/wallpaper_search/wallpaper_search.ts
+++ b/chrome/browser/resources/side_panel/customize_chrome/wallpaper_search/wallpaper_search.ts
@@ -113,6 +113,7 @@
   private descriptors_: Descriptors|null;
   private descriptorD_: string[];
   private emptyContainers_: number[];
+  private errorCallback_: (() => Promise<void>)|undefined;
   private errorState_: ErrorState|null = null;
   private loading_: boolean;
   private results_: WallpaperSearchResult[];
@@ -138,13 +139,7 @@
     this.callbackRouter_ = CustomizeChromeApiProxy.getInstance().callbackRouter;
     this.pageHandler_ = CustomizeChromeApiProxy.getInstance().handler;
     this.wallpaperSearchHandler_ = WallpaperSearchProxy.getHandler();
-    this.wallpaperSearchHandler_.getDescriptors().then(({descriptors}) => {
-      if (descriptors) {
-        this.descriptors_ = descriptors;
-      } else {
-        this.status_ = WallpaperSearchStatus.kError;
-      }
-    });
+    this.fetchDescriptors_();
   }
 
   override connectedCallback() {
@@ -184,6 +179,13 @@
         return {
           title: this.i18n('genericErrorTitle'),
           description: this.i18n('genericErrorDescription'),
+          callToAction: this.i18n('tryAgain'),
+        };
+      case WallpaperSearchStatus.kRequestThrottled:
+        return {
+          title: this.i18n('requestThrottledTitle'),
+          description: this.i18n('requestThrottledDescription'),
+          callToAction: this.i18n('ok'),
         };
     }
   }
@@ -194,6 +196,18 @@
         loadTimeData.getString('wallpaperSearchSubmitBtn');
   }
 
+  private async fetchDescriptors_() {
+    this.wallpaperSearchHandler_.getDescriptors().then(({descriptors}) => {
+      if (descriptors) {
+        this.descriptors_ = descriptors;
+        this.errorCallback_ = undefined;
+      } else {
+        this.errorCallback_ = () => this.fetchDescriptors_();
+        this.status_ = WallpaperSearchStatus.kError;
+      }
+    });
+  }
+
   /**
    * The loading gradient is rendered using a SVG clip path. As typical CSS
    * layouts such as grid cannot apply to clip paths, this ResizeObserver
@@ -254,6 +268,13 @@
     this.$.hueSlider.showAt(this.$.customColorContainer);
   }
 
+  private onErrorClick_() {
+    this.status_ = WallpaperSearchStatus.kOk;
+    if (this.errorCallback_) {
+      this.errorCallback_();
+    }
+  }
+
   private onDefaultColorClick_(e: DomRepeatEvent<string>) {
     this.selectedHue_ = undefined;
     this.selectedDefaultColor_ = e.model.item;
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
index 413addc..85d1ff3 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
@@ -67,8 +67,6 @@
       return "UNAUTHORIZED";
     case Result::FILE_ENCRYPTED:
       return "FILE_ENCRYPTED";
-    case Result::DLP_SCAN_UNSUPPORTED_FILE_TYPE:
-      return "DLP_SCAN_UNSUPPORTED_FILE_TYPE";
     case Result::TOO_MANY_REQUESTS:
       return "TOO_MANY_REQUESTS";
   }
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
index e1a78ac..7a905f36 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
@@ -54,8 +54,9 @@
     // Some or all parts of the file are encrypted.
     FILE_ENCRYPTED = 7,
 
-    // The file's type is not supported and the file was not uploaded.
-    DLP_SCAN_UNSUPPORTED_FILE_TYPE = 8,
+    // Deprecated: The file's type is not supported and the file was not
+    // uploaded.
+    // DLP_SCAN_UNSUPPORTED_FILE_TYPE = 8,
 
     // The server returned a 429 HTTP status indicating too many requests are
     // being sent.
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc
index d1338db..96569a7 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc
@@ -42,8 +42,6 @@
       return "SERVICE_UNAVAILABLE";
     case BinaryUploadService::Result::FILE_ENCRYPTED:
       return "FILE_PASSWORD_PROTECTED";
-    case BinaryUploadService::Result::DLP_SCAN_UNSUPPORTED_FILE_TYPE:
-      return "DLP_SCAN_UNSUPPORTED_FILE_TYPE";
   }
 }
 
@@ -380,8 +378,6 @@
       return "";
     case BinaryUploadService::Result::FILE_ENCRYPTED:
       return "FileEncrypted";
-    case BinaryUploadService::Result::DLP_SCAN_UNSUPPORTED_FILE_TYPE:
-      return "DlpScanUnsupportedFileType";
     case BinaryUploadService::Result::TOO_MANY_REQUESTS:
       return "TooManyRequests";
   }
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils_unittest.cc
index dc61e5e..a86a417 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils_unittest.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils_unittest.cc
@@ -29,7 +29,6 @@
     BinaryUploadService::Result::FAILED_TO_GET_TOKEN,
     BinaryUploadService::Result::UNAUTHORIZED,
     BinaryUploadService::Result::FILE_ENCRYPTED,
-    BinaryUploadService::Result::DLP_SCAN_UNSUPPORTED_FILE_TYPE,
 };
 
 #if !BUILDFLAG(USE_CRASH_KEY_STUBS)
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc
index b44b0034..210e0b9 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc
@@ -30,12 +30,6 @@
 
 namespace {
 
-enterprise_connectors::AnalysisSettings settings(bool block_unsupported_types) {
-  enterprise_connectors::AnalysisSettings settings;
-  settings.block_unsupported_file_types = block_unsupported_types;
-  return settings;
-}
-
 // Helper to cast base::DoNothing.
 BinaryUploadService::ContentAnalysisCallback DoNothingConnector() {
   return base::DoNothing();
@@ -64,14 +58,14 @@
  public:
   FileAnalysisRequestTest() = default;
 
-  std::unique_ptr<FileAnalysisRequest> MakeRequest(bool block_unsupported_types,
-                                                   base::FilePath path,
+  std::unique_ptr<FileAnalysisRequest> MakeRequest(base::FilePath path,
                                                    base::FilePath file_name,
                                                    bool delay_opening_file,
                                                    std::string mime_type = "") {
-    return std::make_unique<FileAnalysisRequest>(
-        settings(block_unsupported_types), path, file_name, mime_type,
-        delay_opening_file, DoNothingConnector());
+    enterprise_connectors::AnalysisSettings settings;
+    return std::make_unique<FileAnalysisRequest>(settings, path, file_name,
+                                                 mime_type, delay_opening_file,
+                                                 DoNothingConnector());
   }
 
   void GetResultsForFileContents(const std::string& file_contents,
@@ -82,9 +76,8 @@
     base::FilePath file_path = temp_dir.GetPath().AppendASCII("normal.doc");
     base::WriteFile(file_path, file_contents);
 
-    auto request =
-        MakeRequest(/*block_unsupported_types=*/false, file_path,
-                    file_path.BaseName(), /*delay_opening_file*/ false);
+    auto request = MakeRequest(file_path, file_path.BaseName(),
+                               /*delay_opening_file*/ false);
 
     base::test::TestFuture<BinaryUploadService::Result,
                            BinaryUploadService::Request::Data>
@@ -108,8 +101,8 @@
   {
     // Non-existent files should return UNKNOWN and have no information set.
     base::FilePath path = temp_dir.GetPath().AppendASCII("not_a_real.doc");
-    auto request = MakeRequest(/*block_unsupported_types=*/false, path,
-                               path.BaseName(), /*delay_opening_file*/ false);
+    auto request =
+        MakeRequest(path, path.BaseName(), /*delay_opening_file*/ false);
 
     base::test::TestFuture<BinaryUploadService::Result,
                            BinaryUploadService::Request::Data>
@@ -128,8 +121,8 @@
     // Directories should not be used as paths passed to GetFileSHA256Blocking,
     // so they should return UNKNOWN and have no information set.
     base::FilePath path = temp_dir.GetPath();
-    auto request = MakeRequest(/*block_unsupported_types=*/false, path,
-                               path.BaseName(), /*delay_opening_file*/ false);
+    auto request =
+        MakeRequest(path, path.BaseName(), /*delay_opening_file*/ false);
 
     base::test::TestFuture<BinaryUploadService::Result,
                            BinaryUploadService::Request::Data>
@@ -148,8 +141,8 @@
     // Empty files should return SUCCESS as they have no content to scan.
     base::FilePath path = temp_dir.GetPath().AppendASCII("empty.doc");
     base::File file(path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
-    auto request = MakeRequest(/*block_unsupported_types=*/false, path,
-                               path.BaseName(), /*delay_opening_file*/ false);
+    auto request =
+        MakeRequest(path, path.BaseName(), /*delay_opening_file*/ false);
 
     base::test::TestFuture<BinaryUploadService::Result,
                            BinaryUploadService::Request::Data>
@@ -285,9 +278,8 @@
   base::File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
   file.WriteAtCurrentPos(file_contents.data(), file_contents.size());
 
-  auto request =
-      MakeRequest(/*block_unsupported_types=*/false, file_path,
-                  file_path.BaseName(), /*delay_opening_file*/ false);
+  auto request = MakeRequest(file_path, file_path.BaseName(),
+                             /*delay_opening_file*/ false);
 
   base::RunLoop run_loop;
   request->GetRequestData(base::IgnoreArgs<BinaryUploadService::Result,
@@ -311,9 +303,8 @@
   base::File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
   file.WriteAtCurrentPos(file_contents.data(), file_contents.size());
 
-  auto request =
-      MakeRequest(/*block_unsupported_types=*/false, file_path,
-                  file_path.BaseName(), /*delay_opening_file*/ false);
+  auto request = MakeRequest(file_path, file_path.BaseName(),
+                             /*delay_opening_file*/ false);
 
   base::RunLoop run_loop;
   request->GetRequestData(base::IgnoreArgs<BinaryUploadService::Result,
@@ -333,9 +324,8 @@
   base::FilePath file_path = temp_dir.GetPath().AppendASCII("normal.doc");
   base::WriteFile(file_path, normal_contents);
 
-  auto request =
-      MakeRequest(/*block_unsupported_types=*/false, file_path,
-                  file_path.BaseName(), /*delay_opening_file*/ false);
+  auto request = MakeRequest(file_path, file_path.BaseName(),
+                             /*delay_opening_file*/ false);
 
   base::test::TestFuture<BinaryUploadService::Result,
                          BinaryUploadService::Request::Data>
@@ -364,9 +354,8 @@
   base::FilePath file_path = temp_dir.GetPath().AppendASCII("normal.doc");
   base::WriteFile(file_path, normal_contents);
 
-  auto request = MakeRequest(/*block_unsupported_types=*/false, file_path,
-                             file_path.BaseName(), /*delay_opening_file*/ false,
-                             "fake/mimetype");
+  auto request = MakeRequest(file_path, file_path.BaseName(),
+                             /*delay_opening_file*/ false, "fake/mimetype");
 
   base::test::TestFuture<BinaryUploadService::Result,
                          BinaryUploadService::Request::Data>
@@ -398,8 +387,8 @@
   base::File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
   file.WriteAtCurrentPos(file_contents.data(), file_contents.size());
 
-  auto request = MakeRequest(/*block_unsupported_types=*/false, file_path,
-                             file_path.BaseName(), /*delay_opening_file*/ true);
+  auto request =
+      MakeRequest(file_path, file_path.BaseName(), /*delay_opening_file*/ true);
 
   base::RunLoop run_loop;
   request->GetRequestData(base::BindLambdaForTesting(
@@ -437,8 +426,8 @@
   test_zip =
       test_zip.AppendASCII("safe_browsing/download_protection/encrypted.zip");
 
-  auto request = MakeRequest(/*block_unsupported_types=*/false, test_zip,
-                             test_zip.BaseName(), /*delay_opening_file*/ false);
+  auto request =
+      MakeRequest(test_zip, test_zip.BaseName(), /*delay_opening_file*/ false);
   request->set_password("12345");
 
   base::test::TestFuture<BinaryUploadService::Result,
@@ -460,8 +449,8 @@
   test_zip =
       test_zip.AppendASCII("safe_browsing/download_protection/encrypted.zip");
 
-  auto request = MakeRequest(/*block_unsupported_types=*/false, test_zip,
-                             test_zip.BaseName(), /*delay_opening_file*/ false);
+  auto request =
+      MakeRequest(test_zip, test_zip.BaseName(), /*delay_opening_file*/ false);
   request->set_password("67890");
 
   base::test::TestFuture<BinaryUploadService::Result,
@@ -500,8 +489,8 @@
                  .AppendASCII("download_protection")
                  .AppendASCII(file_name());
 
-  auto request = MakeRequest(/*block_unsupported_types=*/false, test_zip,
-                             test_zip.BaseName(), /*delay_opening_file*/ false);
+  auto request =
+      MakeRequest(test_zip, test_zip.BaseName(), /*delay_opening_file*/ false);
 
   base::test::TestFuture<BinaryUploadService::Result,
                          BinaryUploadService::Request::Data>
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
index 58bf632..61dfeca 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
@@ -642,10 +642,6 @@
   } else if (result == BinaryUploadService::Result::FILE_ENCRYPTED &&
              analysis_settings_.block_password_protected_files) {
     download_result = DownloadCheckResult::BLOCKED_PASSWORD_PROTECTED;
-  } else if (result ==
-                 BinaryUploadService::Result::DLP_SCAN_UNSUPPORTED_FILE_TYPE &&
-             analysis_settings_.block_unsupported_file_types) {
-    download_result = DownloadCheckResult::BLOCKED_UNSUPPORTED_FILE_TYPE;
   }
 
   LogDeepScanResult(download_result, trigger_,
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
index e36071a..fdb7c571 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
@@ -325,8 +325,6 @@
               default_settings.block_large_files);
     ASSERT_EQ(settings.value().block_password_protected_files,
               default_settings.block_password_protected_files);
-    ASSERT_EQ(settings.value().block_unsupported_file_types,
-              default_settings.block_unsupported_file_types);
     ASSERT_EQ(settings.value().block_until_verdict,
               default_settings.block_until_verdict);
     ASSERT_EQ(settings.value().cloud_or_local_settings.analysis_url(),
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc
index 68d081c..0e9b63e3 100644
--- a/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc
@@ -3692,90 +3692,6 @@
     ClearClientDownloadRequest();
   }
 }
-
-TEST_F(DeepScanningDownloadTest, UnsupportedFiletypeBlockedByPreference) {
-  base::FilePath test_file;
-  ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_file));
-  test_file = test_file.AppendASCII("safe_browsing")
-                  .AppendASCII("download_protection")
-                  .AppendASCII("signed.exe");
-
-  NiceMockDownloadItem item;
-  PrepareBasicDownloadItemWithFullPaths(
-      &item, {"http://www.evil.com/signed.exe"},  // url_chain
-      "http://www.google.com/",                   // referrer
-      test_file,                                  // tmp_path
-      temp_dir_.GetPath().Append(
-          FILE_PATH_LITERAL("signed.exe")));  // final_path
-  content::DownloadItemUtils::AttachInfoForTesting(&item, profile(), nullptr);
-
-  TestBinaryUploadService* test_upload_service =
-      static_cast<TestBinaryUploadService*>(
-          CloudBinaryUploadServiceFactory::GetForProfile(profile()));
-  test_upload_service->SetResponse(
-      BinaryUploadService::Result::DLP_SCAN_UNSUPPORTED_FILE_TYPE,
-      enterprise_connectors::ContentAnalysisResponse());
-
-  EXPECT_CALL(*sb_service_->mock_database_manager(),
-              MatchDownloadAllowlistUrl(_, _))
-      .WillRepeatedly(
-          [](const GURL& url, base::OnceCallback<void(bool)> callback) {
-            std::move(callback).Run(false);
-          });
-  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path_, _))
-      .Times(2);
-  EXPECT_CALL(*binary_feature_extractor_.get(),
-              ExtractImageFeatures(
-                  tmp_path_, BinaryFeatureExtractor::kDefaultOptions, _, _))
-      .Times(2);
-
-  {
-    enterprise_connectors::test::SetAnalysisConnector(
-        profile()->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED, R"(
-                         {
-                           "service_provider": "google",
-                           "enable": [
-                             {"url_list": ["evil.com"], "tags": ["dlp"]}
-                           ],
-                           "block_until_verdict": 1,
-                           "block_unsupported_file_types": true
-                         })");
-    PrepareResponse(ClientDownloadResponse::SAFE, net::HTTP_OK, net::OK);
-
-    RunLoop run_loop;
-    download_service_->CheckClientDownload(
-        &item,
-        base::BindRepeating(&DownloadProtectionServiceTest::CheckDoneCallback,
-                            base::Unretained(this), run_loop.QuitClosure()));
-    run_loop.Run();
-    EXPECT_TRUE(IsResult(DownloadCheckResult::BLOCKED_UNSUPPORTED_FILE_TYPE));
-    EXPECT_TRUE(HasClientDownloadRequest());
-  }
-
-  {
-    enterprise_connectors::test::SetAnalysisConnector(
-        profile()->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED, R"(
-                         {
-                           "service_provider": "google",
-                           "enable": [
-                             {"url_list": ["evil.com"], "tags": ["dlp"]}
-                           ],
-                           "block_until_verdict": 1,
-                           "block_unsupported_file_types": false
-                         })");
-    PrepareResponse(ClientDownloadResponse::SAFE, net::HTTP_OK, net::OK);
-
-    RunLoop run_loop;
-    download_service_->CheckClientDownload(
-        &item,
-        base::BindRepeating(&DownloadProtectionServiceTest::CheckDoneCallback,
-                            base::Unretained(this), run_loop.QuitClosure()));
-    run_loop.Run();
-    EXPECT_TRUE(IsResult(DownloadCheckResult::SAFE));
-    EXPECT_TRUE(HasClientDownloadRequest());
-    ClearClientDownloadRequest();
-  }
-}
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) ||
         // BUILDFLAG(IS_CHROMEOS)
 
diff --git a/chrome/browser/signin/identity_test_environment_profile_adaptor.cc b/chrome/browser/signin/identity_test_environment_profile_adaptor.cc
index a15db58..d946f06 100644
--- a/chrome/browser/signin/identity_test_environment_profile_adaptor.cc
+++ b/chrome/browser/signin/identity_test_environment_profile_adaptor.cc
@@ -8,6 +8,7 @@
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/browser_process.h"
@@ -28,11 +29,7 @@
 IdentityTestEnvironmentProfileAdaptor::CreateProfileForIdentityTestEnvironment(
     const TestingProfile::TestingFactories& input_factories) {
   TestingProfile::Builder builder;
-
-  for (auto& input_factory : input_factories) {
-    builder.AddTestingFactory(input_factory.first, input_factory.second);
-  }
-
+  builder.AddTestingFactories(input_factories);
   return CreateProfileForIdentityTestEnvironment(builder);
 }
 
@@ -40,10 +37,7 @@
 std::unique_ptr<TestingProfile>
 IdentityTestEnvironmentProfileAdaptor::CreateProfileForIdentityTestEnvironment(
     TestingProfile::Builder& builder) {
-  for (auto& identity_factory : GetIdentityTestEnvironmentFactories()) {
-    builder.AddTestingFactory(identity_factory.first, identity_factory.second);
-  }
-
+  builder.AddTestingFactories(GetIdentityTestEnvironmentFactories());
   return builder.Build();
 }
 
@@ -51,8 +45,11 @@
 void IdentityTestEnvironmentProfileAdaptor::
     SetIdentityTestEnvironmentFactoriesOnBrowserContext(
         content::BrowserContext* context) {
-  for (const auto& factory_pair : GetIdentityTestEnvironmentFactories()) {
-    factory_pair.first->SetTestingFactory(context, factory_pair.second);
+  for (const auto& f : GetIdentityTestEnvironmentFactories()) {
+    CHECK_EQ(f.service_factory_and_testing_factory.index(), 0u);
+    const auto& [service_factory, testing_factory] =
+        absl::get<0>(f.service_factory_and_testing_factory);
+    service_factory->SetTestingFactory(context, testing_factory);
   }
 }
 
diff --git a/chrome/browser/tpcd/experiment/tpcd_experiment_features.cc b/chrome/browser/tpcd/experiment/tpcd_experiment_features.cc
index 425e01f..ea07b54 100644
--- a/chrome/browser/tpcd/experiment/tpcd_experiment_features.cc
+++ b/chrome/browser/tpcd/experiment/tpcd_experiment_features.cc
@@ -87,6 +87,12 @@
     "TpcdWritePopupPastInteractionHeuristicsGrants";
 const char kTpcdBackfillPopupHeuristicsGrantsName[] =
     "TpcdBackfillPopupHeuristicsGrants";
+const char kTpcdWriteRedirectHeuristicGrantsName[] =
+    "TpcdWriteRedirectHeuristicGrants";
+const char kTpcdRedirectHeuristicRequireABAFlowName[] =
+    "TpcdRedirectHeuristicRequireABAFlow";
+const char kTpcdRedirectHeuristicRequireCurrentInteractionName[] =
+    "TpcdRedirectHeuristicRequireCurrentInteraction";
 
 const base::FeatureParam<base::TimeDelta>
     kTpcdWritePopupCurrentInteractionHeuristicsGrants{
@@ -101,18 +107,18 @@
 
 const base::FeatureParam<base::TimeDelta> kTpcdBackfillPopupHeuristicsGrants{
     &content_settings::features::kTpcdHeuristicsGrants,
-    /*name=*/"TpcdBackfillPopupHeuristicsGrants", base::TimeDelta()};
+    kTpcdBackfillPopupHeuristicsGrantsName, base::TimeDelta()};
 
 const base::FeatureParam<base::TimeDelta> kTpcdWriteRedirectHeuristicGrants{
     &content_settings::features::kTpcdHeuristicsGrants,
-    /*name=*/"TpcdWriteRedirectHeuristicGrants", base::TimeDelta()};
+    kTpcdWriteRedirectHeuristicGrantsName, base::TimeDelta()};
 
 const base::FeatureParam<bool> kTpcdRedirectHeuristicRequireABAFlow{
     &content_settings::features::kTpcdHeuristicsGrants,
-    /*name=*/"TpcdRedirectHeuristicRequireABAFlow", true};
+    kTpcdRedirectHeuristicRequireABAFlowName, true};
 
 const base::FeatureParam<bool> kTpcdRedirectHeuristicRequireCurrentInteraction{
     &content_settings::features::kTpcdHeuristicsGrants,
-    /*name=*/"TpcdRedirectHeuristicRequireCurrentInteraction", true};
+    kTpcdRedirectHeuristicRequireCurrentInteractionName, true};
 
 }  // namespace tpcd::experiment
diff --git a/chrome/browser/tpcd/experiment/tpcd_experiment_features.h b/chrome/browser/tpcd/experiment/tpcd_experiment_features.h
index 680591b..79ad45a 100644
--- a/chrome/browser/tpcd/experiment/tpcd_experiment_features.h
+++ b/chrome/browser/tpcd/experiment/tpcd_experiment_features.h
@@ -54,23 +54,31 @@
 extern const char kTpcdWritePopupCurrentInteractionHeuristicsGrantsName[];
 extern const char kTpcdWritePopupPastInteractionHeuristicsGrantsName[];
 extern const char kTpcdBackfillPopupHeuristicsGrantsName[];
+extern const char kTpcdWriteRedirectHeuristicGrantsName[];
+extern const char kTpcdRedirectHeuristicRequireABAFlowName[];
+extern const char kTpcdRedirectHeuristicRequireCurrentInteractionName[];
 
-// Whether to create a short-term grant when observing the Popup With Current
-// Interaction scenario.
+// The duration of the storage access grant created when observing the Popup
+// With Current Interaction scenario. If set to zero duration, do not create a
+// grant.
 extern const base::FeatureParam<base::TimeDelta>
     kTpcdWritePopupCurrentInteractionHeuristicsGrants;
 
-// Whether to create a short-term grant when observing the Popup With Past
-// Interaction scenario.
+// The duration of the storage access grant created when observing the Popup
+// With Past Interaction scenario. If set to zero duration, do not create a
+// grant.
 extern const base::FeatureParam<base::TimeDelta>
     kTpcdWritePopupPastInteractionHeuristicsGrants;
 
-// Whether to backfill popup heuristics grants for recent popups with a current
-// interaction, when a user is onboarded to 3PCD.
+// The lookback and duration of the storage access grants created when
+// backfilling the Popup With Current Interaction scenario on onboarding to
+// 3PCD. If set to zero duration, to not create backfill grants.
 extern const base::FeatureParam<base::TimeDelta>
     kTpcdBackfillPopupHeuristicsGrants;
 
-// Whether to create a short-term grant when observing the Redirect scenario.
+// The duration of the storage access grant created when observing the Redirect
+// With Current Interaction scenario. If set to zero duration, do not create a
+// grant.
 extern const base::FeatureParam<base::TimeDelta>
     kTpcdWriteRedirectHeuristicGrants;
 
diff --git a/chrome/browser/ui/android/signin/java/res/layout/fre_uma_dialog.xml b/chrome/browser/ui/android/signin/java/res/layout/fre_uma_dialog.xml
index cd9ccdf..e8d13a66 100644
--- a/chrome/browser/ui/android/signin/java/res/layout/fre_uma_dialog.xml
+++ b/chrome/browser/ui/android/signin/java/res/layout/fre_uma_dialog.xml
@@ -32,7 +32,7 @@
                 android:text="@string/signin_fre_uma_dialog_title"
                 android:textAppearance="@style/TextAppearance.Headline.Primary" />
 
-            <com.google.android.material.switchmaterial.SwitchMaterial
+            <org.chromium.components.browser_ui.widget.MaterialSwitchWithText
                 android:id="@+id/fre_uma_dialog_switch"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogCoordinator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogCoordinator.java
index 304e14c3..a64659e 100644
--- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogCoordinator.java
+++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/FreUMADialogCoordinator.java
@@ -10,9 +10,8 @@
 
 import androidx.annotation.MainThread;
 
-import com.google.android.material.switchmaterial.SwitchMaterial;
-
 import org.chromium.chrome.browser.ui.signin.R;
+import org.chromium.components.browser_ui.widget.MaterialSwitchWithText;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType;
@@ -53,7 +52,7 @@
         mView.findViewById(R.id.fre_uma_dialog_dismiss_button).setOnClickListener(v -> {
             mDialogManager.dismissDialog(mModel, DialogDismissalCause.ACTION_ON_CONTENT);
         });
-        final SwitchMaterial umaSwitch = mView.findViewById(R.id.fre_uma_dialog_switch);
+        final MaterialSwitchWithText umaSwitch = mView.findViewById(R.id.fre_uma_dialog_switch);
         umaSwitch.setChecked(allowMetricsAndCrashUploading);
         umaSwitch.setOnCheckedChangeListener(
                 (compoundButton,
diff --git a/chrome/browser/ui/android/toolbar/BUILD.gn b/chrome/browser/ui/android/toolbar/BUILD.gn
index 1ec15d5..3fac664 100644
--- a/chrome/browser/ui/android/toolbar/BUILD.gn
+++ b/chrome/browser/ui/android/toolbar/BUILD.gn
@@ -132,6 +132,7 @@
     "//chrome/browser/feature_engagement:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/fullscreen/android:java",
+    "//chrome/browser/hub:java",
     "//chrome/browser/incognito:java",
     "//chrome/browser/language/android:java",
     "//chrome/browser/paint_preview/android:java",
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
index e3b357f..2ab7e8f 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
@@ -22,6 +22,7 @@
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.device.DeviceClassManager;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
+import org.chromium.chrome.browser.hub.HubFieldTrial;
 import org.chromium.chrome.browser.layouts.LayoutManager;
 import org.chromium.chrome.browser.layouts.LayoutStateProvider;
 import org.chromium.chrome.browser.layouts.LayoutType;
@@ -213,6 +214,9 @@
                     startSurfaceLogoClickedCallback, mIsStartSurfaceRefactorEnabled,
                     shouldCreateLogoInStartToolbar, this::onStartSurfaceToolbarTransitionFinished,
                     mToolbarColorObserverManager);
+        } else if (HubFieldTrial.isHubEnabled()) {
+            // Hub has an entirely separate toolbar.
+            mTabSwitcherModeCoordinator = null;
         } else if (mToolbarLayout instanceof ToolbarPhone
                 || mToolbarLayout instanceof ToolbarTablet) {
             mTabSwitcherModeCoordinator = new TabSwitcherModeTTCoordinator(toolbarStub,
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 5d43d43..d5f9eec 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -389,6 +389,12 @@
                              description_template);
 }
 
+void ChromeShellDelegate::OpenProfileManager() {
+  if (crosapi::BrowserManager::Get()->IsRunning()) {
+    crosapi::BrowserManager::Get()->OpenProfileManager();
+  }
+}
+
 // static
 void ChromeShellDelegate::SetDisableLoggingRedirectForTesting(bool value) {
   disable_logging_redirect_for_testing = value;
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h
index 69a3ded..7cb97e46 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.h
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -78,6 +78,7 @@
   base::FilePath GetPrimaryUserDownloadsFolder() const override;
   void OpenFeedbackDialog(ShellDelegate::FeedbackSource source,
                           const std::string& description_template) override;
+  void OpenProfileManager() override;
   static void SetDisableLoggingRedirectForTesting(bool value);
   static void ResetDisableLoggingRedirectForTesting();
   const GURL& GetLastCommittedURLForWindowIfAny(aura::Window* window) override;
diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h
index c445bab2..4a65ef7 100644
--- a/chrome/browser/ui/color/chrome_color_id.h
+++ b/chrome/browser/ui/color/chrome_color_id.h
@@ -424,7 +424,6 @@
   E_CPONLY(kColorSidePanelCustomizeChromeThemeCheckmarkBackground) \
   E_CPONLY(kColorSidePanelCustomizeChromeThemeCheckmarkForeground) \
   E_CPONLY(kColorSidePanelCustomizeChromeThemeSnapshotBackground) \
-  E_CPONLY(kColorSidePanelCustomizeChromeWallpaperSearchTileBackground) \
   E_CPONLY(kColorSidePanelCustomizeChromeWebStoreBorder) \
   E_CPONLY(kColorSidePanelDialogBackground) \
   E_CPONLY(kColorSidePanelDialogDivider) \
@@ -432,6 +431,7 @@
   E_CPONLY(kColorSidePanelDialogSecondaryForeground) \
   E_CPONLY(kColorSidePanelDivider) \
   E_CPONLY(kColorSidePanelEditFooterBorder) \
+  E_CPONLY(kColorSidePanelComboboxEntryIcon) \
   E_CPONLY(kColorSidePanelEntryIcon) \
   E_CPONLY(kColorSidePanelEntryDropdownIcon) \
   E_CPONLY(kColorSidePanelEntryTitle) \
@@ -447,6 +447,9 @@
   E_CPONLY(kColorSidePanelResizeAreaHandle) \
   E_CPONLY(kColorSidePanelScrollbarThumb) \
   E_CPONLY(kColorSidePanelTextfieldBorder) \
+  E_CPONLY(kColorSidePanelWallpaperSearchTileBackground) \
+  E_CPONLY(kColorSidePanelWallpaperSearchErrorButtonBackground) \
+  E_CPONLY(kColorSidePanelWallpaperSearchErrorButtonText) \
   /* Status bubble colors. */ \
   E_CPONLY(kColorStatusBubbleBackgroundFrameActive) \
   E_CPONLY(kColorStatusBubbleBackgroundFrameInactive) \
diff --git a/chrome/browser/ui/color/chrome_color_mixer.cc b/chrome/browser/ui/color/chrome_color_mixer.cc
index a5585a00..71a62053 100644
--- a/chrome/browser/ui/color/chrome_color_mixer.cc
+++ b/chrome/browser/ui/color/chrome_color_mixer.cc
@@ -367,7 +367,9 @@
   mixer[kColorShareThisTabSourceViewBorder] = {ui::kColorMidground};
   mixer[kColorSidePanelBackground] = {kColorToolbar};
   mixer[kColorSidePanelContentAreaSeparator] = {ui::kColorSeparator};
+  mixer[kColorSidePanelComboboxEntryIcon] = {ui::kColorIcon};
   mixer[kColorSidePanelEntryIcon] = {ui::kColorIcon};
+  mixer[kColorSidePanelEntryTitle] = {ui::kColorLabelForeground};
   mixer[kColorSidePanelEntryDropdownIcon] = {ui::kColorIcon};
   mixer[kColorSidePanelHeaderButtonIcon] = {ui::kColorIcon};
   mixer[kColorSidePanelHeaderButtonIconDisabled] = {ui::kColorIconDisabled};
diff --git a/chrome/browser/ui/color/material_chrome_color_mixer.cc b/chrome/browser/ui/color/material_chrome_color_mixer.cc
index bc742da..2fb4b58d 100644
--- a/chrome/browser/ui/color/material_chrome_color_mixer.cc
+++ b/chrome/browser/ui/color/material_chrome_color_mixer.cc
@@ -121,7 +121,7 @@
     mixer[kColorComposeDialogTextarea] = {ui::kColorSysOnSurface};
     mixer[kColorComposeDialogTextareaOutline] = {ui::kColorSysNeutralOutline};
     mixer[kColorComposeDialogTextareaPlaceholder] = {
-        ui::kColorSysOnSurfaceSecondary};
+        ui::kColorSysOnSurfaceSubtle};
     mixer[kColorComposeDialogTextareaReadonlyBackground] = {
         ui::kColorSysNeutralContainer};
     mixer[kColorComposeDialogTextareaReadonlyForeground] = {
diff --git a/chrome/browser/ui/color/material_side_panel_color_mixer.cc b/chrome/browser/ui/color/material_side_panel_color_mixer.cc
index 106e9156..2d0fdce3 100644
--- a/chrome/browser/ui/color/material_side_panel_color_mixer.cc
+++ b/chrome/browser/ui/color/material_side_panel_color_mixer.cc
@@ -15,15 +15,16 @@
                                     const ui::ColorProviderKey& key) {
   ui::ColorMixer& mixer = provider->AddMixer();
   mixer[kColorSidePanelContentBackground] = {ui::kColorSysBaseContainer};
-  mixer[kColorSidePanelEntryIcon] = {ui::kColorSysPrimary};
+  mixer[kColorSidePanelComboboxEntryIcon] = {ui::kColorSysPrimary};
   mixer[kColorSidePanelEntryDropdownIcon] = {ui::kColorSysOnSurfaceSubtle};
-  mixer[kColorSidePanelEntryTitle] = {ui::kColorSysOnSurface};
   mixer[kColorSidePanelContentAreaSeparator] = {ui::kColorSysBaseContainer};
 
-  // After ChromeRefresh2023 roll out these three should be moved to replace
+  // After ChromeRefresh2023 roll out these five should be moved to replace
   // their colors in c/b/ui/color/chrome_color_mixer.cc. For now they need a
   // separate themed ChromeRefresh2023 color because the side panel header has a
   // different background color than it did before.
+  mixer[kColorSidePanelEntryIcon] = {kColorToolbarText};
+  mixer[kColorSidePanelEntryTitle] = {kColorToolbarText};
   mixer[kColorSidePanelHeaderButtonIcon] = {kColorToolbarText};
   mixer[kColorSidePanelHeaderButtonIconDisabled] = {kColorToolbarTextDisabled};
   mixer[kColorSidePanelResizeAreaHandle] = {kColorToolbarText};
@@ -106,10 +107,14 @@
       ui::kColorSysOnPrimary};
   mixer[kColorSidePanelCustomizeChromeThemeSnapshotBackground] = {
       ui::kColorSysTonalContainer};
-  mixer[kColorSidePanelCustomizeChromeWallpaperSearchTileBackground] = {
-      ui::kColorSysSurface2};
   mixer[kColorSidePanelCustomizeChromeWebStoreBorder] = {
       ui::kColorSysNeutralOutline};
+  /*Customize Chrome Wallpaper Search*/
+  mixer[kColorSidePanelWallpaperSearchErrorButtonBackground] = {
+      ui::kColorSysTonalContainer};
+  mixer[kColorSidePanelWallpaperSearchErrorButtonText] = {
+      ui::kColorSysOnTonalContainer};
+  mixer[kColorSidePanelWallpaperSearchTileBackground] = {ui::kColorSysSurface2};
 
   /* Commerce */
   mixer[kColorSidePanelCommerceGraphAxis] = {ui::kColorSysDivider};
@@ -121,6 +126,8 @@
   if (!ShouldApplyChromeMaterialOverrides(key)) {
     return;
   }
+  mixer[kColorSidePanelEntryIcon] = {ui::kColorSysPrimary};
+  mixer[kColorSidePanelEntryTitle] = {ui::kColorSysOnSurface};
   mixer[kColorSidePanelHeaderButtonIcon] = {ui::kColorSysOnSurfaceSubtle};
   mixer[kColorSidePanelHeaderButtonIconDisabled] = {ui::kColorSysStateDisabled};
   mixer[kColorSidePanelResizeAreaHandle] = {ui::kColorSysOnSurfaceSubtle};
diff --git a/chrome/browser/ui/login/login_handler_browsertest.cc b/chrome/browser/ui/login/login_handler_browsertest.cc
index f9c7f8f2..2362372 100644
--- a/chrome/browser/ui/login/login_handler_browsertest.cc
+++ b/chrome/browser/ui/login/login_handler_browsertest.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/login/login_handler_test_utils.h"
 #include "chrome/browser/ui/tabs/tab_enums.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -378,12 +379,7 @@
 
   observer.Register(content::Source<NavigationController>(controller));
 
-  WindowedLoadStopObserver load_stop_waiter(controller, 1);
-  browser()->OpenURL(OpenURLParams(test_page, Referrer(),
-                                   WindowOpenDisposition::CURRENT_TAB,
-                                   ui::PAGE_TRANSITION_TYPED, false));
-
-  load_stop_waiter.Wait();
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page));
   EXPECT_TRUE(observer.handlers().empty());
 }
 
@@ -713,7 +709,6 @@
   observer.Register(content::Source<NavigationController>(controller));
 
   // One LOAD_STOP event for kAuthURL and second for kNoAuthURL.
-  WindowedLoadStopObserver load_stop_waiter(controller, 2);
   WindowedAuthNeededObserver auth_needed_waiter(controller);
   browser()->OpenURL(OpenURLParams(kAuthURL, Referrer(),
                                    WindowOpenDisposition::CURRENT_TAB,
@@ -722,7 +717,6 @@
   // Navigating while auth is requested is the same as cancelling.
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), kNoAuthURL));
   auth_cancelled_waiter.Wait();
-  load_stop_waiter.Wait();
   EXPECT_TRUE(observer.handlers().empty());
 }
 
@@ -742,18 +736,14 @@
   // go back to.
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), kNoAuthURL));
 
-  WindowedLoadStopObserver load_stop_waiter(controller, 1);
   WindowedAuthNeededObserver auth_needed_waiter(controller);
-  browser()->OpenURL(OpenURLParams(kAuthURL, Referrer(),
-                                   WindowOpenDisposition::CURRENT_TAB,
-                                   ui::PAGE_TRANSITION_TYPED, false));
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), kAuthURL));
   auth_needed_waiter.Wait();
   WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
   // Navigating back while auth is requested is the same as cancelling.
   ASSERT_TRUE(controller->CanGoBack());
   controller->GoBack();
   auth_cancelled_waiter.Wait();
-  load_stop_waiter.Wait();
   EXPECT_TRUE(observer.handlers().empty());
 }
 
@@ -833,11 +823,8 @@
   login_prompt_observer_.Register(
       content::Source<NavigationController>(controller));
 
-  WindowedLoadStopObserver load_stop_waiter(controller, 1);
-
-  browser()->OpenURL(OpenURLParams(test_page, Referrer(),
-                                   WindowOpenDisposition::CURRENT_TAB,
-                                   ui::PAGE_TRANSITION_TYPED, false));
+  NavigateParams params(browser(), test_page, ui::PAGE_TRANSITION_TYPED);
+  Navigate(&params);
 
   // Need to have LoginHandlers created for all requests that need
   // authentication.
@@ -859,7 +846,7 @@
     for_each_realm_func(*it);
   }
 
-  load_stop_waiter.Wait();
+  content::WaitForLoadStop(params.navigated_or_inserted_contents);
 }
 
 // Checks that cancelling works as expected.
@@ -969,22 +956,15 @@
   // authentication.  There should be no login prompt.
   {
     GURL test_page = embedded_test_server()->GetURL(kFaviconTestPage);
-    WindowedLoadStopObserver load_stop_waiter(controller, 1);
-    browser()->OpenURL(OpenURLParams(test_page, Referrer(),
-                                     WindowOpenDisposition::CURRENT_TAB,
-                                     ui::PAGE_TRANSITION_TYPED, false));
-    load_stop_waiter.Wait();
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page));
   }
 
   // Now request the same favicon, but directly as the document.
   // There should be one login prompt.
   {
     GURL test_page = embedded_test_server()->GetURL(kFaviconResource);
-    WindowedLoadStopObserver load_stop_waiter(controller, 1);
     WindowedAuthNeededObserver auth_needed_waiter(controller);
-    browser()->OpenURL(OpenURLParams(test_page, Referrer(),
-                                     WindowOpenDisposition::CURRENT_TAB,
-                                     ui::PAGE_TRANSITION_TYPED, false));
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page));
     auth_needed_waiter.Wait();
     ASSERT_EQ(1u, observer.handlers().size());
 
@@ -996,8 +976,6 @@
       handler->CancelAuth();
       auth_cancelled_waiter.Wait();
     }
-
-    load_stop_waiter.Wait();
   }
 
   EXPECT_EQ(0, observer.auth_supplied_count());
@@ -1030,11 +1008,7 @@
     replacements.SetHostStr("www.a.com");
     test_page = test_page.ReplaceComponents(replacements);
 
-    WindowedLoadStopObserver load_stop_waiter(controller, 1);
-    browser()->OpenURL(OpenURLParams(test_page, Referrer(),
-                                     WindowOpenDisposition::CURRENT_TAB,
-                                     ui::PAGE_TRANSITION_TYPED, false));
-    load_stop_waiter.Wait();
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page));
   }
 
   EXPECT_EQ(0, observer.auth_needed_count());
@@ -1090,11 +1064,7 @@
     GURL test_page = embedded_test_server()->GetURL(kTestPage);
     ASSERT_EQ("127.0.0.1", test_page.host());
 
-    WindowedLoadStopObserver load_stop_waiter(controller, 1);
-    browser()->OpenURL(OpenURLParams(test_page, Referrer(),
-                                     WindowOpenDisposition::CURRENT_TAB,
-                                     ui::PAGE_TRANSITION_TYPED, false));
-    load_stop_waiter.Wait();
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page));
   }
   EXPECT_EQ(0, observer.auth_needed_count());
 
@@ -1155,11 +1125,7 @@
   test_page = test_page.ReplaceComponents(replacements);
   image_url = image_url.ReplaceComponents(replacements);
 
-  WindowedLoadStopObserver load_stop_waiter(controller, 1);
-  browser()->OpenURL(OpenURLParams(test_page, Referrer(),
-                                   WindowOpenDisposition::CURRENT_TAB,
-                                   ui::PAGE_TRANSITION_TYPED, false));
-  load_stop_waiter.Wait();
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page));
   EXPECT_EQ(0, observer.auth_needed_count());
 }
 
@@ -1403,11 +1369,7 @@
   // resource with the wrong credentials.  There should be no login prompt.
   {
     GURL test_page = embedded_test_server()->GetURL(kXHRTestPage);
-    WindowedLoadStopObserver load_stop_waiter(controller, 1);
-    browser()->OpenURL(OpenURLParams(test_page, Referrer(),
-                                     WindowOpenDisposition::CURRENT_TAB,
-                                     ui::PAGE_TRANSITION_TYPED, false));
-    load_stop_waiter.Wait();
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page));
   }
 
   std::u16string expected_title(u"status=401");
@@ -1437,11 +1399,7 @@
   // resource with the wrong credentials.  There should be no login prompt.
   {
     GURL test_page = embedded_test_server()->GetURL(kXHRTestPage);
-    WindowedLoadStopObserver load_stop_waiter(controller, 1);
-    browser()->OpenURL(OpenURLParams(test_page, Referrer(),
-                                     WindowOpenDisposition::CURRENT_TAB,
-                                     ui::PAGE_TRANSITION_TYPED, false));
-    load_stop_waiter.Wait();
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page));
   }
 
   std::u16string expected_title(u"status=200");
@@ -1504,8 +1462,8 @@
   handler->SetAuth(username, password);
   auth_supplied_waiter.Wait();
 
-  WindowedLoadStopObserver load_stop_waiter(controller, 1);
-  load_stop_waiter.Wait();
+  content::WaitForLoadStop(
+      browser()->tab_strip_model()->GetActiveWebContents());
 
   std::u16string expected_title(u"status=200");
 
@@ -1548,8 +1506,8 @@
   handler->CancelAuth();
   auth_cancelled_waiter.Wait();
 
-  WindowedLoadStopObserver load_stop_waiter(controller, 1);
-  load_stop_waiter.Wait();
+  content::WaitForLoadStop(
+      browser()->tab_strip_model()->GetActiveWebContents());
 
   std::u16string expected_title(u"status=401");
 
@@ -1781,7 +1739,6 @@
   // www.b.com.
   WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
   {
-    WindowedLoadStopObserver load_stop_observer(controller, 1);
     EXPECT_TRUE(content::ExecJs(
         contents, std::string("document.location='") + page2.spec() + "';"));
     auth_cancelled_waiter.Wait();
@@ -1789,7 +1746,7 @@
     WindowedAuthNeededObserver auth_needed_waiter(controller);
     auth_needed_waiter.Wait();
     ASSERT_EQ(1u, observer.handlers().size());
-    load_stop_observer.Wait();
+    content::WaitForLoadStop(contents);
   }
 
   EXPECT_EQ("www.b.com", contents->GetVisibleURL().host());
diff --git a/chrome/browser/ui/login/login_handler_test_utils.cc b/chrome/browser/ui/login/login_handler_test_utils.cc
index 1c096fd..1301d46e 100644
--- a/chrome/browser/ui/login/login_handler_test_utils.cc
+++ b/chrome/browser/ui/login/login_handler_test_utils.cc
@@ -62,22 +62,3 @@
 void LoginPromptBrowserTestObserver::UnregisterAll() {
   registrar_.RemoveAll();
 }
-
-WindowedLoadStopObserver::WindowedLoadStopObserver(
-    content::NavigationController* controller,
-    int notification_count)
-    : WindowedNavigationObserver<content::NOTIFICATION_LOAD_STOP>(controller),
-      remaining_notification_count_(notification_count) {
-  // This should really be an ASSERT, if those were allowed in a method which
-  // does not return void.
-  EXPECT_LE(0, remaining_notification_count_);
-}
-
-void WindowedLoadStopObserver::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  ASSERT_LT(0, remaining_notification_count_);
-  if (--remaining_notification_count_ == 0)
-    WindowedNotificationObserver::Observe(type, source, details);
-}
diff --git a/chrome/browser/ui/login/login_handler_test_utils.h b/chrome/browser/ui/login/login_handler_test_utils.h
index 5fb36ab0..f2a6a31 100644
--- a/chrome/browser/ui/login/login_handler_test_utils.h
+++ b/chrome/browser/ui/login/login_handler_test_utils.h
@@ -87,24 +87,4 @@
 typedef WindowedNavigationObserver<chrome::NOTIFICATION_AUTH_SUPPLIED>
     WindowedAuthSuppliedObserver;
 
-// LOAD_STOP observer is special since we want to be able to wait for
-// multiple LOAD_STOP events.
-class WindowedLoadStopObserver
-    : public WindowedNavigationObserver<content::NOTIFICATION_LOAD_STOP> {
- public:
-  WindowedLoadStopObserver(content::NavigationController* controller,
-                           int notification_count);
-
-  WindowedLoadStopObserver(const WindowedLoadStopObserver&) = delete;
-  WindowedLoadStopObserver& operator=(const WindowedLoadStopObserver&) = delete;
-
- protected:
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
-
- private:
-  int remaining_notification_count_;  // Number of notifications remaining.
-};
-
 #endif  // CHROME_BROWSER_UI_LOGIN_LOGIN_HANDLER_TEST_UTILS_H_
diff --git a/chrome/browser/ui/performance_controls/battery_saver_button_controller.cc b/chrome/browser/ui/performance_controls/battery_saver_button_controller.cc
index 09dbfd51..9a8c41b 100644
--- a/chrome/browser/ui/performance_controls/battery_saver_button_controller.cc
+++ b/chrome/browser/ui/performance_controls/battery_saver_button_controller.cc
@@ -27,7 +27,7 @@
   UpdateVisibilityState(is_active);
 }
 
-void BatterySaverButtonController::OnBatterySaverModeChanged(bool is_active) {
+void BatterySaverButtonController::OnBatterySaverActiveChanged(bool is_active) {
   UpdateVisibilityState(is_active);
 }
 
diff --git a/chrome/browser/ui/performance_controls/battery_saver_button_controller.h b/chrome/browser/ui/performance_controls/battery_saver_button_controller.h
index a33ac30..a8f84f92a 100644
--- a/chrome/browser/ui/performance_controls/battery_saver_button_controller.h
+++ b/chrome/browser/ui/performance_controls/battery_saver_button_controller.h
@@ -28,7 +28,7 @@
   void Init(BatterySaverButtonControllerDelegate* delegate);
 
   // BatterySaverModeManager::Observer:
-  void OnBatterySaverModeChanged(bool is_active) override;
+  void OnBatterySaverActiveChanged(bool is_active) override;
 
  private:
   void UpdateVisibilityState(bool is_active);
diff --git a/chrome/browser/ui/performance_controls/performance_controls_hats_service.cc b/chrome/browser/ui/performance_controls/performance_controls_hats_service.cc
index 104ca4b6..638622f 100644
--- a/chrome/browser/ui/performance_controls/performance_controls_hats_service.cc
+++ b/chrome/browser/ui/performance_controls/performance_controls_hats_service.cc
@@ -17,29 +17,22 @@
 #include "components/performance_manager/public/user_tuning/prefs.h"
 #include "components/prefs/pref_service.h"
 
-PerformanceControlsHatsService::PerformanceControlsHatsService(
-    PrefService* local_state,
-    Profile* profile)
-    : local_state_(local_state), profile_(profile) {
-  if (local_state) {
-    if (base::FeatureList::IsEnabled(
-            performance_manager::features::
-                kPerformanceControlsHighEfficiencyOptOutSurvey)) {
-      performance_manager::user_tuning::UserPerformanceTuningManager::
-          GetInstance()
-              ->AddObserver(this);
-    }
+PerformanceControlsHatsService::PerformanceControlsHatsService(Profile* profile)
+    : profile_(profile) {
+  if (base::FeatureList::IsEnabled(
+          performance_manager::features::
+              kPerformanceControlsHighEfficiencyOptOutSurvey)) {
+    performance_manager::user_tuning::UserPerformanceTuningManager::
+        GetInstance()
+            ->AddObserver(this);
+  }
 
-    local_pref_registrar_.Init(local_state);
-    if (base::FeatureList::IsEnabled(
-            performance_manager::features::
-                kPerformanceControlsBatterySaverOptOutSurvey)) {
-      local_pref_registrar_.Add(
-          performance_manager::user_tuning::prefs::kBatterySaverModeState,
-          base::BindRepeating(
-              &PerformanceControlsHatsService::OnBatterySaverModeChange,
-              base::Unretained(this)));
-    }
+  if (base::FeatureList::IsEnabled(
+          performance_manager::features::
+              kPerformanceControlsBatterySaverOptOutSurvey)) {
+    auto* manager = performance_manager::user_tuning::BatterySaverModeManager::
+        GetInstance();
+    battery_saver_observer_.Observe(manager);
   }
 }
 
@@ -56,35 +49,15 @@
   }
 }
 
-void PerformanceControlsHatsService::OnBatterySaverModeChange() {
-  HatsService* hats_service = HatsServiceFactory::GetForProfile(profile_, true);
-  if (!hats_service) {
-    return;
-  }
-
-  // A survey for users who have turned off battery saver.
-  if (local_state_->GetInteger(
-          performance_manager::user_tuning::prefs::kBatterySaverModeState) ==
-      static_cast<int>(performance_manager::user_tuning::prefs::
-                           BatterySaverModeState::kDisabled)) {
-    auto* pref = local_state_->FindPreference(
-        performance_manager::user_tuning::prefs::kBatterySaverModeState);
-    if (!pref->IsManaged()) {
-      hats_service->LaunchDelayedSurvey(
-          kHatsSurveyTriggerPerformanceControlsBatterySaverOptOut, 10000);
-    }
-  }
-}
-
 void PerformanceControlsHatsService::OpenedNewTabPage() {
   HatsService* hats_service = HatsServiceFactory::GetForProfile(profile_, true);
   if (!hats_service) {
     return;
   }
 
-  const int battery_saver_mode = local_state_->GetInteger(
-      performance_manager::user_tuning::prefs::kBatterySaverModeState);
-
+  const bool battery_saver_mode =
+      performance_manager::user_tuning::BatterySaverModeManager::GetInstance()
+          ->IsBatterySaverModeEnabled();
   const bool high_efficiency_mode =
       performance_manager::user_tuning::UserPerformanceTuningManager::
           GetInstance()
@@ -93,10 +66,11 @@
   // A general performance survey for all users.
   if (base::FeatureList::IsEnabled(performance_manager::features::
                                        kPerformanceControlsPerformanceSurvey)) {
-    hats_service->LaunchSurvey(
-        kHatsSurveyTriggerPerformanceControlsPerformance, base::DoNothing(),
-        base::DoNothing(), {{"high_efficiency_mode", high_efficiency_mode}},
-        {{"battery_saver_mode", base::NumberToString(battery_saver_mode)}});
+    hats_service->LaunchSurvey(kHatsSurveyTriggerPerformanceControlsPerformance,
+                               base::DoNothing(), base::DoNothing(),
+                               {{"high_efficiency_mode", high_efficiency_mode},
+                                {"battery_saver_mode", battery_saver_mode}},
+                               {});
   }
 
   base::Time last_battery_timestamp =
@@ -113,8 +87,25 @@
     hats_service->LaunchSurvey(
         kHatsSurveyTriggerPerformanceControlsBatteryPerformance,
         base::DoNothing(), base::DoNothing(),
-        {{"high_efficiency_mode", high_efficiency_mode}},
-        {{"battery_saver_mode", base::NumberToString(battery_saver_mode)}});
+        {{"high_efficiency_mode", high_efficiency_mode},
+         {"battery_saver_mode", battery_saver_mode}},
+        {});
+  }
+}
+
+void PerformanceControlsHatsService::OnBatterySaverModeChanged(
+    bool is_enabled) {
+  HatsService* hats_service = HatsServiceFactory::GetForProfile(profile_, true);
+  if (!hats_service) {
+    return;
+  }
+
+  auto* manager =
+      performance_manager::user_tuning::BatterySaverModeManager::GetInstance();
+  // A survey for users who have turned off battery saver.
+  if (!is_enabled && !manager->IsBatterySaverModeManaged()) {
+    hats_service->LaunchDelayedSurvey(
+        kHatsSurveyTriggerPerformanceControlsBatterySaverOptOut, 10000);
   }
 }
 
diff --git a/chrome/browser/ui/performance_controls/performance_controls_hats_service.h b/chrome/browser/ui/performance_controls/performance_controls_hats_service.h
index aa7312b..06a56ea 100644
--- a/chrome/browser/ui/performance_controls/performance_controls_hats_service.h
+++ b/chrome/browser/ui/performance_controls/performance_controls_hats_service.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_PERFORMANCE_CONTROLS_HATS_SERVICE_H_
 #define CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_PERFORMANCE_CONTROLS_HATS_SERVICE_H_
 
+#include "chrome/browser/performance_manager/public/user_tuning/battery_saver_mode_manager.h"
 #include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -13,28 +14,34 @@
 class PerformanceControlsHatsService
     : public KeyedService,
       public performance_manager::user_tuning::UserPerformanceTuningManager::
+          Observer,
+      public performance_manager::user_tuning::BatterySaverModeManager::
           Observer {
  public:
-  PerformanceControlsHatsService(PrefService* local_state, Profile* profile);
+  explicit PerformanceControlsHatsService(Profile* profile);
   ~PerformanceControlsHatsService() override;
 
-  // Called in response to a change in the battery saver mode pref to check
-  // whether a HaTS survey should be shown.
-  void OnBatterySaverModeChange();
-
   // Called when the user opens an NTP. This allows the service to check if one
   // of the performance controls surveys should be shown.
   void OpenedNewTabPage();
 
+  // BatterySaverModeManager::Observer:
+  // Called in response to a change in the battery saver mode pref to check
+  // whether a HaTS survey should be shown.
+  void OnBatterySaverModeChanged(bool is_active) override;
+
   // performance_manager::user_tuning::UserPerformanceTuningManager::Observer:
   // Called in response to a change in the high efficiency mode pref to check
   // whether a HaTS survey should be shown.
   void OnHighEfficiencyModeChanged() override;
 
  private:
-  raw_ptr<PrefService> local_state_;
   raw_ptr<Profile> profile_;
   PrefChangeRegistrar local_pref_registrar_;
+  base::ScopedObservation<
+      performance_manager::user_tuning::BatterySaverModeManager,
+      performance_manager::user_tuning::BatterySaverModeManager::Observer>
+      battery_saver_observer_{this};
 };
 
 #endif  // CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_PERFORMANCE_CONTROLS_HATS_SERVICE_H_
diff --git a/chrome/browser/ui/performance_controls/performance_controls_hats_service_factory.cc b/chrome/browser/ui/performance_controls/performance_controls_hats_service_factory.cc
index 6eb0c13..9fef4ae 100644
--- a/chrome/browser/ui/performance_controls/performance_controls_hats_service_factory.cc
+++ b/chrome/browser/ui/performance_controls/performance_controls_hats_service_factory.cc
@@ -34,7 +34,6 @@
 PerformanceControlsHatsService*
 PerformanceControlsHatsServiceFactory::GetForProfile(Profile* profile) {
   return static_cast<PerformanceControlsHatsService*>(
-      g_browser_process->local_state(),
       GetInstance()->GetServiceForBrowserContext(profile, /*create=*/true));
 }
 
@@ -65,12 +64,12 @@
   // Chrome) and simply not creating the service avoids unnecessary work
   // tracking user interactions.
   auto* hats_service =
-      HatsServiceFactory::GetForProfile(profile, /*create_if_necessary=*/true);
+      HatsServiceFactory::GetForProfile(profile,
+                                        /*create_if_necessary=*/true);
   if (!hats_service ||
       !hats_service->CanShowAnySurvey(/*user_prompted=*/false)) {
     return nullptr;
   }
 
-  return std::make_unique<PerformanceControlsHatsService>(
-      g_browser_process->local_state(), profile);
+  return std::make_unique<PerformanceControlsHatsService>(profile);
 }
diff --git a/chrome/browser/ui/performance_controls/performance_controls_hats_service_unittest.cc b/chrome/browser/ui/performance_controls/performance_controls_hats_service_unittest.cc
index fc4e0fb4..eaa0130 100644
--- a/chrome/browser/ui/performance_controls/performance_controls_hats_service_unittest.cc
+++ b/chrome/browser/ui/performance_controls/performance_controls_hats_service_unittest.cc
@@ -49,8 +49,7 @@
     environment_.SetUp(&local_state_);
 
     performance_controls_hats_service_ =
-        std::make_unique<PerformanceControlsHatsService>(&local_state_,
-                                                         profile);
+        std::make_unique<PerformanceControlsHatsService>(profile);
   }
 
   void TearDown() override {
@@ -159,12 +158,9 @@
   SetBatterySaverMode(performance_manager::user_tuning::prefs::
                           BatterySaverModeState::kEnabledBelowThreshold);
 
-  SurveyBitsData expected_bits = {{"high_efficiency_mode", false}};
-  SurveyStringData expected_strings = {
-      {"battery_saver_mode",
-       base::NumberToString(static_cast<int>(
-           performance_manager::user_tuning::prefs::BatterySaverModeState::
-               kEnabledBelowThreshold))}};
+  SurveyBitsData expected_bits = {{"high_efficiency_mode", false},
+                                  {"battery_saver_mode", true}};
+  SurveyStringData expected_strings = {};
   EXPECT_CALL(*mock_hats_service(),
               LaunchSurvey(kHatsSurveyTriggerPerformanceControlsPerformance, _,
                            _, expected_bits, expected_strings));
diff --git a/chrome/browser/ui/tabs/organization/tab_organization_request.cc b/chrome/browser/ui/tabs/organization/tab_organization_request.cc
index 59de0da..a14b656e 100644
--- a/chrome/browser/ui/tabs/organization/tab_organization_request.cc
+++ b/chrome/browser/ui/tabs/organization/tab_organization_request.cc
@@ -79,6 +79,10 @@
 void TabOrganizationRequest::FailRequest() {
   CHECK(state_ != State::COMPLETED);
   state_ = State::FAILED;
+
+  if (response_callback_) {
+    std::move(response_callback_).Run(response_.get());
+  }
 }
 
 void TabOrganizationRequest::CancelRequest() {
@@ -87,4 +91,7 @@
   state_ = State::CANCELED;
 
   std::move(backend_cancel_request_lambda_).Run(this);
+  if (response_callback_) {
+    std::move(response_callback_).Run(response_.get());
+  }
 }
diff --git a/chrome/browser/ui/tabs/organization/tab_organization_session.cc b/chrome/browser/ui/tabs/organization/tab_organization_session.cc
index 239c64d3..51c62f4 100644
--- a/chrome/browser/ui/tabs/organization/tab_organization_session.cc
+++ b/chrome/browser/ui/tabs/organization/tab_organization_session.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <vector>
 
+#include "base/logging.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/organization/request_factory.h"
 #include "chrome/browser/ui/tabs/organization/tab_data.h"
@@ -31,7 +32,11 @@
   kNextSessionID++;
 }
 
-TabOrganizationSession::~TabOrganizationSession() = default;
+TabOrganizationSession::~TabOrganizationSession() {
+  for (auto& observer : observers_) {
+    observer.OnTabOrganizationSessionDestroyed(session_id());
+  }
+}
 
 // static
 std::unique_ptr<TabOrganizationSession>
@@ -82,16 +87,51 @@
   return GetNextTabOrganization();
 }
 
+void TabOrganizationSession::AddObserver(
+    TabOrganizationSession::Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void TabOrganizationSession::RemoveObserver(
+    TabOrganizationSession::Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void TabOrganizationSession::OnTabOrganizationUpdated(
+    const TabOrganization* organization) {
+  NotifyObserversOfUpdate();
+}
+
+void TabOrganizationSession::OnTabOrganizationDestroyed(
+    TabOrganization::ID organization_id) {
+  NotifyObserversOfUpdate();
+}
+
 void TabOrganizationSession::StartRequest() {
   CHECK(request_);
   request_->SetResponseCallback(base::BindOnce(
-      &TabOrganizationSession::PopulateAndCreate, base::Unretained(this)));
+      &TabOrganizationSession::OnRequestResponse, base::Unretained(this)));
   request_->StartRequest();
+  NotifyObserversOfUpdate();
   if (service_) {
     service_->OnStartRequest(session_id_);
   }
 }
 
+void TabOrganizationSession::NotifyObserversOfUpdate() {
+  for (auto& observer : observers_) {
+    observer.OnTabOrganizationSessionUpdated(this);
+  }
+}
+
+void TabOrganizationSession::OnRequestResponse(
+    const TabOrganizationResponse* response) {
+  if (response) {
+    PopulateAndCreate(response);
+  }
+  NotifyObserversOfUpdate();
+}
+
 void TabOrganizationSession::PopulateAndCreate(
     const TabOrganizationResponse* response) {
   PopulateOrganizations(response);
diff --git a/chrome/browser/ui/tabs/organization/tab_organization_session.h b/chrome/browser/ui/tabs/organization/tab_organization_session.h
index 05faddd2..61fbf2d 100644
--- a/chrome/browser/ui/tabs/organization/tab_organization_session.h
+++ b/chrome/browser/ui/tabs/organization/tab_organization_session.h
@@ -17,17 +17,27 @@
 class Browser;
 class TabOrganizationService;
 
-class TabOrganizationSession {
+class TabOrganizationSession : public TabOrganization::Observer {
  public:
   // TODO(dpenning): make this a base::Token.
   using ID = int;
   using TabOrganizations = std::vector<std::unique_ptr<TabOrganization>>;
 
+  class Observer {
+   public:
+    virtual ~Observer() = default;
+
+    virtual void OnTabOrganizationSessionUpdated(
+        const TabOrganizationSession* session) {}
+    virtual void OnTabOrganizationSessionDestroyed(
+        TabOrganizationSession::ID session_id) {}
+  };
+
   TabOrganizationSession();
   explicit TabOrganizationSession(
       const TabOrganizationService* service,
       std::unique_ptr<TabOrganizationRequest> request);
-  ~TabOrganizationSession();
+  ~TabOrganizationSession() override;
 
   const TabOrganizationRequest* request() const { return request_.get(); }
   const TabOrganizations& tab_organizations() const {
@@ -53,7 +63,21 @@
   // that need to be taken on organizations.
   bool IsComplete() const;
 
+  void AddObserver(Observer* new_observer);
+  void RemoveObserver(Observer* new_observer);
+
+  // TabOrganization::Observer
+  void OnTabOrganizationUpdated(const TabOrganization* organization) override;
+  void OnTabOrganizationDestroyed(TabOrganization::ID organization_id) override;
+
  private:
+  // Notifies observers of the tab data that it has been updated.
+  void NotifyObserversOfUpdate();
+
+  // Checks whether there is a response, and if so calls Populate functions.
+  // Notifies observers that the session has been updated.
+  void OnRequestResponse(const TabOrganizationResponse* response);
+
   // TODO: Remove once the full UI flow is implemented.
   void PopulateAndCreate(const TabOrganizationResponse* response);
 
@@ -65,6 +89,8 @@
   std::unique_ptr<TabOrganizationRequest> request_;
   TabOrganizations tab_organizations_;
   ID session_id_;
+
+  base::ObserverList<Observer>::Unchecked observers_;
 };
 
 #endif  // CHROME_BROWSER_UI_TABS_ORGANIZATION_TAB_ORGANIZATION_SESSION_H_
diff --git a/chrome/browser/ui/tabs/organization/tab_organization_unittest.cc b/chrome/browser/ui/tabs/organization/tab_organization_unittest.cc
index 11acbbe5..f5ed7d8 100644
--- a/chrome/browser/ui/tabs/organization/tab_organization_unittest.cc
+++ b/chrome/browser/ui/tabs/organization/tab_organization_unittest.cc
@@ -86,6 +86,34 @@
   const std::unique_ptr<TabStripModel> tab_strip_model_;
 };
 
+class SessionObserver : public TabOrganizationSession::Observer {
+ public:
+  void OnTabOrganizationSessionUpdated(
+      const TabOrganizationSession* session) override {
+    update_call_count++;
+  }
+
+  void OnTabOrganizationSessionDestroyed(
+      TabOrganizationSession::ID session_id) override {
+    if (!session_) {
+      return;
+    }
+
+    destroy_call_count++;
+    session_ = nullptr;
+  }
+
+  ~SessionObserver() override {
+    if (session_) {
+      session_->RemoveObserver(this);
+    }
+  }
+
+  int update_call_count = 0;
+  int destroy_call_count = 0;
+  raw_ptr<TabOrganizationSession> session_;
+};
+
 // TabData tests.
 
 // The constructor that takes the webcontents and tabstrip model should
@@ -445,6 +473,7 @@
           std::vector<std::unique_ptr<TabData>>{},
           std::vector<std::u16string>{u"Organization"}, 0, absl::nullopt);
   TestObserver observer;
+  observer.tab_organization_ = organization.get();
   organization->AddObserver(&observer);
   observer.tab_organization_ = organization.get();
 
@@ -472,7 +501,7 @@
       std::make_unique<TabData>(tab_strip_model(), AddTab(tab_strip_model())));
   EXPECT_EQ(observer.update_call_count, 4);
 
-  // Make changes to the organization, expect the update method to be called.
+  // Accept the organization, expect the update method to be called.
   organization->Accept();
   EXPECT_EQ(observer.update_call_count, 5);
 
@@ -773,3 +802,90 @@
           tab_strip_model()->GetIndexOfWebContents(tab_to_not_group));
   EXPECT_FALSE(group_for_tab_to_not_group.has_value());
 }
+
+TEST_F(TabOrganizationTest, TabOrganizationSessionObserverFail) {
+  std::unique_ptr<TabOrganizationRequest> request =
+      std::make_unique<TabOrganizationRequest>();
+  TabOrganizationRequest* request_ptr = request.get();
+
+  std::unique_ptr<TabOrganizationSession> session =
+      std::make_unique<TabOrganizationSession>(nullptr, std::move(request));
+
+  std::unique_ptr<SessionObserver> observer =
+      std::make_unique<SessionObserver>();
+  session->AddObserver(observer.get());
+  observer->session_ = session.get();
+
+  session->StartRequest();
+  EXPECT_EQ(observer->update_call_count, 1);
+
+  request_ptr->FailRequest();
+  EXPECT_EQ(observer->update_call_count, 2);
+}
+
+TEST_F(TabOrganizationTest, TabOrganizationSessionObserverCompleteRequest) {
+  std::unique_ptr<TabOrganizationRequest> request =
+      std::make_unique<TabOrganizationRequest>();
+  TabOrganizationRequest* request_ptr = request.get();
+
+  std::unique_ptr<TabOrganizationSession> session =
+      std::make_unique<TabOrganizationSession>(nullptr, std::move(request));
+
+  std::unique_ptr<SessionObserver> observer =
+      std::make_unique<SessionObserver>();
+  session->AddObserver(observer.get());
+  observer->session_ = session.get();
+
+  session->StartRequest();
+  EXPECT_EQ(observer->update_call_count, 1);
+
+  request_ptr->CompleteRequestForTesting({});
+  EXPECT_EQ(observer->update_call_count, 2);
+}
+
+TEST_F(TabOrganizationTest, TabOrganizationSessionObserverOrganizationUpdate) {
+  std::unique_ptr<TabOrganizationRequest> request =
+      std::make_unique<TabOrganizationRequest>();
+  TabOrganizationRequest* request_ptr = request.get();
+
+  // Add a couple tabs with different URLs.
+  for (int i = 0; i < 5; i++) {
+    content::WebContents* tab = AddTab();
+    request->AddTabData(std::make_unique<TabData>(tab_strip_model(), tab));
+  }
+
+  // Add 2 tabs that are grouped in the response.
+  content::WebContents* tab_to_group_1 = AddTab();
+  TabData* tab_to_group_data_1 = request->AddTabData(
+      std::make_unique<TabData>(tab_strip_model(), tab_to_group_1));
+
+  content::WebContents* tab_to_group_2 = AddTab();
+  TabData* tab_to_group_data_2 = request->AddTabData(
+      std::make_unique<TabData>(tab_strip_model(), tab_to_group_2));
+
+  content::WebContents* tab_to_not_group = AddTab();
+  request->AddTabData(
+      std::make_unique<TabData>(tab_strip_model(), tab_to_not_group));
+
+  std::unique_ptr<TabOrganizationSession> session =
+      std::make_unique<TabOrganizationSession>(nullptr, std::move(request));
+
+  std::unique_ptr<SessionObserver> observer =
+      std::make_unique<SessionObserver>();
+  session->AddObserver(observer.get());
+  observer->session_ = session.get();
+
+  std::vector<TabOrganizationResponse::Organization> response_organizations;
+  TabOrganizationResponse::Organization organization(
+      u"title", {tab_to_group_data_1->tab_id(), tab_to_group_data_2->tab_id()});
+  response_organizations.emplace_back(std::move(organization));
+
+  std::unique_ptr<TabOrganizationResponse> response =
+      std::make_unique<TabOrganizationResponse>(response_organizations);
+
+  session->StartRequest();
+  EXPECT_EQ(observer->update_call_count, 1);
+
+  request_ptr->CompleteRequestForTesting(std::move(response));
+  EXPECT_EQ(observer->update_call_count, 2);
+}
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index b05c201..c342ccd 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -945,7 +945,7 @@
   return kBookmarksBarLeadingMarginWithoutSavedTabGroups;
 }
 
-views::MenuItemView* BookmarkBarView::GetMenu() {
+const views::MenuItemView* BookmarkBarView::GetMenu() const {
   return bookmark_menu_ ? bookmark_menu_->menu() : nullptr;
 }
 
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
index 1e3ef83..ac2c5744 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <set>
+#include <utility>
 
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
@@ -16,6 +17,7 @@
 #include "chrome/browser/ui/bookmarks/bookmark_stats.h"
 #include "chrome/browser/ui/tabs/tab_group_theme.h"
 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_observer.h"
+#include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.h"
 #include "chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.h"
 #include "components/bookmarks/browser/bookmark_model_observer.h"
 #include "components/bookmarks/browser/bookmark_node_data.h"
@@ -131,8 +133,11 @@
 
   const gfx::Animation& size_animation() { return size_animation_; }
 
-  // Returns the active MenuItemView, or NULL if a menu isn't showing.
-  views::MenuItemView* GetMenu();
+  // Returns the active MenuItemView, or null if a menu isn't showing.
+  const views::MenuItemView* GetMenu() const;
+  views::MenuItemView* GetMenu() {
+    return const_cast<views::MenuItemView*>(std::as_const(*this).GetMenu());
+  }
 
   // Returns the context menu, or null if one isn't showing.
   views::MenuItemView* GetContextMenu();
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 678dde09..87273dce0 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
@@ -21,6 +21,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/single_thread_task_runner.h"
+#include "base/test/bind.h"
 #include "build/build_config.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -95,8 +96,7 @@
 #if !BUILDFLAG(IS_MAC)
 
 // Waits for a views::Widget dialog to show up.
-class DialogWaiter : public aura::EnvObserver,
-                     public views::WidgetObserver {
+class DialogWaiter : public aura::EnvObserver, public views::WidgetObserver {
  public:
   DialogWaiter() { aura::Env::GetInstance()->AddObserver(this); }
 
@@ -106,8 +106,9 @@
   ~DialogWaiter() override { aura::Env::GetInstance()->RemoveObserver(this); }
 
   views::Widget* WaitForDialog() {
-    if (dialog_created_)
+    if (dialog_created_) {
       return dialog_;
+    }
     base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
     quit_closure_ = run_loop.QuitClosure();
     run_loop.Run();
@@ -117,11 +118,13 @@
  private:
   // aura::EnvObserver:
   void OnWindowInitialized(aura::Window* window) override {
-    if (dialog_)
+    if (dialog_) {
       return;
+    }
     views::Widget* widget = views::Widget::GetWidgetForNativeView(window);
-    if (!widget || !widget->IsDialogBox())
+    if (!widget || !widget->IsDialogBox()) {
       return;
+    }
     dialog_ = widget;
     dialog_->AddObserver(this);
   }
@@ -132,8 +135,9 @@
     if (active) {
       dialog_created_ = true;
       dialog_->RemoveObserver(this);
-      if (!quit_closure_.is_null())
+      if (!quit_closure_.is_null()) {
         quit_closure_.Run();
+      }
     }
   }
 
@@ -145,8 +149,7 @@
 // Waits for a dialog to terminate.
 class DialogCloseWaiter : public views::WidgetObserver {
  public:
-  explicit DialogCloseWaiter(views::Widget* dialog)
-      : dialog_closed_(false) {
+  explicit DialogCloseWaiter(views::Widget* dialog) : dialog_closed_(false) {
     dialog->AddObserver(this);
   }
 
@@ -159,8 +162,9 @@
   }
 
   void WaitForDialogClose() {
-    if (dialog_closed_)
+    if (dialog_closed_) {
       return;
+    }
     base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
     quit_closure_ = run_loop.QuitClosure();
     run_loop.Run();
@@ -170,8 +174,9 @@
   // views::WidgetObserver:
   void OnWidgetDestroyed(views::Widget* widget) override {
     dialog_closed_ = true;
-    if (!quit_closure_.is_null())
+    if (!quit_closure_.is_null()) {
       quit_closure_.Run();
+    }
   }
 
   bool dialog_closed_;
@@ -182,8 +187,7 @@
 class TabKeyWaiter : public ui::EventHandler {
  public:
   explicit TabKeyWaiter(views::Widget* widget)
-      : widget_(widget),
-        received_tab_(false) {
+      : widget_(widget), received_tab_(false) {
     widget_->GetNativeWindow()->AddPreTargetHandler(this);
   }
 
@@ -195,8 +199,9 @@
   }
 
   void WaitForTab() {
-    if (received_tab_)
+    if (received_tab_) {
       return;
+    }
     base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
     quit_closure_ = run_loop.QuitClosure();
     run_loop.Run();
@@ -208,8 +213,9 @@
     if (event->type() == ui::ET_KEY_RELEASED &&
         event->key_code() == ui::VKEY_TAB) {
       received_tab_ = true;
-      if (!quit_closure_.is_null())
+      if (!quit_closure_.is_null()) {
         quit_closure_.Run();
+      }
     }
   }
 
@@ -412,6 +418,31 @@
   // See comment above class description for what this does.
   virtual bool CreateBigMenu() { return false; }
 
+  bool MenuIsShowing(const views::MenuItemView* menu) const {
+    if (!menu) {
+      return false;
+    }
+    const views::SubmenuView* const submenu = menu->GetSubmenu();
+    return submenu && submenu->IsShowing();
+  }
+  // Sugar for "The main menu is showing". Can't use a default arg to the above
+  // since `bb_view_` is non-static.
+  bool MenuIsShowing() const { return MenuIsShowing(bb_view_->GetMenu()); }
+
+  // Clicks `view`, which is expected to open a top-level menu from the bookmark
+  // bar, then calls `callback`.
+  void OpenMenuByClick(views::View* view, base::OnceClosure callback) {
+    ui_test_utils::MoveMouseToCenterAndPress(
+        view, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
+        base::BindOnce(&BookmarkBarViewEventTestBase::RunTestMethod,
+                       base::Unretained(this),
+                       base::BindLambdaForTesting(
+                           [&, callback = std::move(callback)]() mutable {
+                             ASSERT_TRUE(MenuIsShowing());
+                             std::move(callback).Run();
+                           })));
+  }
+
   raw_ptr<BookmarkModel, AcrossTasksDanglingUntriaged> model_ = nullptr;
   raw_ptr<BookmarkBarView, AcrossTasksDanglingUntriaged> bb_view_ = nullptr;
   TestingPageNavigator navigator_;
@@ -505,20 +536,14 @@
 
     // Move the mouse to the first folder on the bookmark bar and press the
     // mouse.
-    views::LabelButton* button = GetBookmarkButton(0);
-    ui_test_utils::MoveMouseToCenterAndPress(
-        button, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
+    OpenMenuByClick(
+        GetBookmarkButton(0),
         CreateEventTask(this, &BookmarkBarViewDragTestBase::OnMenuOpened));
   }
 
   virtual void OnMenuOpened() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_NE(nullptr, menu);
-    views::SubmenuView* submenu = menu->GetSubmenu();
-    ASSERT_TRUE(submenu->IsShowing());
-
     // The menu is showing, so it has a widget we can observe now.
+    views::SubmenuView* submenu = bb_view_->GetMenu()->GetSubmenu();
     widget_observations_.AddObservation(submenu->GetWidget());
 
     // Move mouse to center of node f1a and press button.
@@ -581,30 +606,21 @@
   void DoTestOnMessageLoop() override {
     // Move the mouse to the first folder on the bookmark bar and press the
     // mouse.
-    views::LabelButton* button = GetBookmarkButton(0);
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest1::Step2));
+    OpenMenuByClick(GetBookmarkButton(0),
+                    CreateEventTask(this, &BookmarkBarViewTest1::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
     // Button should be depressed.
     views::LabelButton* button = GetBookmarkButton(0);
-    ASSERT_TRUE(button->GetState() == views::Button::STATE_PRESSED);
+    ASSERT_EQ(views::Button::STATE_PRESSED, button->GetState());
 
     // Click on the 2nd menu item (A URL).
-    ASSERT_TRUE(menu->GetSubmenu());
-
     views::MenuItemView* menu_to_select =
-        menu->GetSubmenu()->GetMenuItemAt(0);
-    ui_test_utils::MoveMouseToCenterAndPress(menu_to_select, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(0);
+    ui_test_utils::MoveMouseToCenterAndPress(
+        menu_to_select, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest1::Step3));
   }
 
@@ -616,11 +632,9 @@
 
     // Make sure button is no longer pushed.
     views::LabelButton* button = GetBookmarkButton(0);
-    ASSERT_TRUE(button->GetState() == views::Button::STATE_NORMAL);
+    ASSERT_EQ(views::Button::STATE_NORMAL, button->GetState());
 
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu == nullptr || !menu->GetSubmenu()->IsShowing());
-
+    ASSERT_FALSE(MenuIsShowing());
     Done();
   }
 };
@@ -633,18 +647,12 @@
   void DoTestOnMessageLoop() override {
     // Move the mouse to the first folder on the bookmark bar and press the
     // mouse.
-    views::LabelButton* button = GetBookmarkButton(0);
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest2::Step2));
+    OpenMenuByClick(GetBookmarkButton(0),
+                    CreateEventTask(this, &BookmarkBarViewTest2::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr && menu->GetSubmenu()->IsShowing());
-
     // Click on 0x0, which should trigger closing menu.
     // NOTE: this code assume there is a left margin, which is currently
     // true. If that changes, this code will need to find another empty space
@@ -665,13 +673,11 @@
   }
 
   void Step4() {
-    // The menu shouldn't be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu == nullptr || !menu->GetSubmenu()->IsShowing());
+    ASSERT_FALSE(MenuIsShowing());
 
     // Make sure button is no longer pushed.
     views::LabelButton* button = GetBookmarkButton(0);
-    ASSERT_TRUE(button->GetState() == views::Button::STATE_NORMAL);
+    ASSERT_EQ(views::Button::STATE_NORMAL, button->GetState());
 
     Done();
   }
@@ -684,64 +690,45 @@
 class BookmarkBarViewTest3 : public BookmarkBarViewEventTestBase {
  protected:
   void DoTestOnMessageLoop() override {
-    // Move the mouse to the first folder on the bookmark bar and press the
-    // mouse.
-    views::MenuButton* button = bb_view_->all_bookmarks_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest3::Step2));
+    // Move the mouse to the "All Bookmarks" button and press the mouse.
+    OpenMenuByClick(bb_view_->all_bookmarks_button(),
+                    CreateEventTask(this, &BookmarkBarViewTest3::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
-    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
-    ASSERT_TRUE(child_menu != nullptr);
+    views::MenuItemView* child_menu =
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(2);
+    ASSERT_NE(nullptr, child_menu);
 
     // Click on second child, which has a submenu.
-    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
+    ui_test_utils::MoveMouseToCenterAndPress(
+        child_menu, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest3::Step3));
   }
 
   void Step3() {
-    // Make sure sub menu is showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu);
-    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
-    ASSERT_TRUE(child_menu->GetSubmenu() != nullptr);
-    ASSERT_TRUE(child_menu->GetSubmenu()->IsShowing());
+    views::SubmenuView* submenu = bb_view_->GetMenu()->GetSubmenu();
+    ASSERT_TRUE(MenuIsShowing(submenu->GetMenuItemAt(2)));
 
     // Click on third child, which has a submenu too.
-    child_menu = menu->GetSubmenu()->GetMenuItemAt(3);
-    ASSERT_TRUE(child_menu != nullptr);
-    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
+    views::MenuItemView* child_menu = submenu->GetMenuItemAt(3);
+    ASSERT_NE(nullptr, child_menu);
+    ui_test_utils::MoveMouseToCenterAndPress(
+        child_menu, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest3::Step4));
   }
 
   void Step4() {
-    // Make sure sub menu we first clicked isn't showing.
     views::MenuItemView* menu = bb_view_->GetMenu();
-    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
-    ASSERT_TRUE(child_menu->GetSubmenu() != nullptr);
-    ASSERT_FALSE(child_menu->GetSubmenu()->IsShowing());
-
-    // And submenu we last clicked is showing.
-    child_menu = menu->GetSubmenu()->GetMenuItemAt(3);
-    ASSERT_TRUE(child_menu != nullptr);
-    ASSERT_TRUE(child_menu->GetSubmenu()->IsShowing());
+    views::SubmenuView* submenu = menu->GetSubmenu();
+    ASSERT_FALSE(MenuIsShowing(submenu->GetMenuItemAt(2)));
+    ASSERT_TRUE(MenuIsShowing(submenu->GetMenuItemAt(3)));
 
     // Nothing should have been selected.
     EXPECT_EQ(GURL(), wrapper_.last_url());
 
-    // Hide menu.
     menu->GetMenuController()->Cancel(views::MenuController::ExitType::kAll);
-
     Done();
   }
 };
@@ -782,28 +769,20 @@
 class BookmarkBarViewTest4 : public BookmarkBarViewEventTestBase {
  public:
   BookmarkBarViewTest4()
-      : observer_(CreateEventTask(this, &BookmarkBarViewTest4::Step3)) {
-  }
+      : observer_(CreateEventTask(this, &BookmarkBarViewTest4::Step3)) {}
 
  protected:
   void DoTestOnMessageLoop() override {
-    // Move the mouse to the first folder on the bookmark bar and press the
-    // mouse.
-    views::LabelButton* button = bb_view_->all_bookmarks_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest4::Step2));
+    // Move the mouse to the "All Bookmarks" button and press the mouse.
+    OpenMenuByClick(bb_view_->all_bookmarks_button(),
+                    CreateEventTask(this, &BookmarkBarViewTest4::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
-    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(1);
-    ASSERT_TRUE(child_menu != nullptr);
+    views::MenuItemView* child_menu =
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
+    ASSERT_NE(nullptr, child_menu);
 
     // Right click on the first child to get its context menu.
     ui_test_utils::MoveMouseToCenterAndPress(
@@ -813,15 +792,12 @@
   }
 
   void Step3() {
-    // Make sure the context menu is showing.
-    views::MenuItemView* menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu());
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
+    ASSERT_TRUE(MenuIsShowing(context_menu));
 
     // Select the first menu item (open).
     ui_test_utils::MoveMouseToCenterAndPress(
-        menu->GetSubmenu()->GetMenuItemAt(1), ui_controls::LEFT,
+        context_menu->GetSubmenu()->GetMenuItemAt(1), ui_controls::LEFT,
         ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest4::Step4));
   }
@@ -871,24 +847,21 @@
   void DoTestOnMessageLoop() override {
     // Press the mouse button on the overflow button. Don't release it though.
     views::LabelButton* button = bb_view_->overflow_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN, CreateEventTask(this, &BookmarkBarViewTest6::Step2));
+    ui_test_utils::MoveMouseToCenterAndPress(
+        button, ui_controls::LEFT, ui_controls::DOWN,
+        CreateEventTask(this, &BookmarkBarViewTest6::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
     views::MenuItemView* child_menu =
-        menu->GetSubmenu()->GetMenuItemAt(0);
-    ASSERT_TRUE(child_menu != nullptr);
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(0);
+    ASSERT_NE(nullptr, child_menu);
 
     // Move mouse to center of menu and release mouse.
-    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
-        ui_controls::UP, CreateEventTask(this, &BookmarkBarViewTest6::Step3));
+    ui_test_utils::MoveMouseToCenterAndPress(
+        child_menu, ui_controls::LEFT, ui_controls::UP,
+        CreateEventTask(this, &BookmarkBarViewTest6::Step3));
   }
 
   void Step3() {
@@ -908,16 +881,14 @@
   // BookmarkBarViewDragTestBase:
   void OnDropMenuShown() override {
     views::MenuItemView* drop_menu = bb_view_->GetDropMenu();
-    ASSERT_NE(nullptr, drop_menu);
-    views::SubmenuView* drop_submenu = drop_menu->GetSubmenu();
-    ASSERT_TRUE(drop_submenu->IsShowing());
+    ASSERT_TRUE(MenuIsShowing(drop_menu));
 
     // The button should be highlighted now.
     EXPECT_EQ(views::Button::STATE_PRESSED,
               bb_view_->all_bookmarks_button()->GetState());
 
     // Cause the target view to trigger a mouse up when dragged over.
-    const views::View* target_view = drop_submenu->GetMenuItemAt(1);
+    const views::View* target_view = drop_menu->GetSubmenu()->GetMenuItemAt(1);
     SetStopDraggingView(target_view);
 
     // Drag to the top of the target view. Use 2 instead of 0 for target.y
@@ -960,9 +931,7 @@
   // BookmarkBarViewDragTestBase:
   void OnDropMenuShown() override {
     views::MenuItemView* drop_menu = bb_view_->GetDropMenu();
-    ASSERT_NE(nullptr, drop_menu);
-    views::SubmenuView* drop_submenu = drop_menu->GetSubmenu();
-    ASSERT_TRUE(drop_submenu->IsShowing());
+    ASSERT_TRUE(MenuIsShowing(drop_menu));
 
     const views::View* target_view;
     const auto* controller =
@@ -972,7 +941,7 @@
       target_view = GetBookmarkButton(0);
     } else {
       // Drag to folder F11.
-      target_view = drop_submenu->GetMenuItemAt(1);
+      target_view = drop_menu->GetSubmenu()->GetMenuItemAt(1);
 
       // Cause folder F11 to trigger a mouse up when dragged over.
       SetStopDraggingView(target_view);
@@ -1008,34 +977,26 @@
   void DoTestOnMessageLoop() override {
     // Move the mouse to the first folder on the bookmark bar and press the
     // mouse.
-    views::LabelButton* button = GetBookmarkButton(0);
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest9::Step2));
+    OpenMenuByClick(GetBookmarkButton(0),
+                    CreateEventTask(this, &BookmarkBarViewTest9::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
-    first_menu_ = menu->GetSubmenu()->GetMenuItemAt(0);
+    views::SubmenuView* submenu = bb_view_->GetMenu()->GetSubmenu();
     gfx::Point menu_loc;
-    views::View::ConvertPointToScreen(first_menu_, &menu_loc);
+    views::View::ConvertPointToScreen(submenu->GetMenuItemAt(0), &menu_loc);
     start_y_ = menu_loc.y();
 
     // Move the mouse over the scroll button.
-    views::View* scroll_container = menu->GetSubmenu()->parent();
-    ASSERT_TRUE(scroll_container != nullptr);
+    views::View* scroll_container = submenu->parent();
+    ASSERT_NE(nullptr, scroll_container);
     scroll_container = scroll_container->parent();
-    ASSERT_TRUE(scroll_container != nullptr);
+    ASSERT_NE(nullptr, scroll_container);
     views::View* scroll_down_button = scroll_container->children()[2];
-    ASSERT_TRUE(scroll_down_button);
-    gfx::Point loc(scroll_down_button->width() / 2,
-                   scroll_down_button->height() / 2);
-    views::View::ConvertPointToScreen(scroll_down_button, &loc);
+    ASSERT_NE(nullptr, scroll_down_button);
+    const gfx::Point loc =
+        ui_test_utils::GetCenterInScreenCoordinates(scroll_down_button);
 
     // On linux, the sending one location isn't enough.
     ASSERT_TRUE(ui_controls::SendMouseMove(loc.x() - 1, loc.y() - 1));
@@ -1052,18 +1013,16 @@
 
   void Step4() {
     gfx::Point menu_loc;
-    views::View::ConvertPointToScreen(first_menu_, &menu_loc);
+    views::View::ConvertPointToScreen(
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(0), &menu_loc);
     ASSERT_NE(start_y_, menu_loc.y());
 
-    // Hide menu.
     bb_view_->GetMenu()->GetMenuController()->Cancel(
         views::MenuController::ExitType::kAll);
-
     Done();
   }
 
-  int start_y_;
-  raw_ptr<views::MenuItemView, AcrossTasksDanglingUntriaged> first_menu_;
+  int start_y_ = 0;
 };
 
 #if BUILDFLAG(IS_LINUX)  // TODO(crbug.com/1216392): Flakily times out on Linux.
@@ -1079,19 +1038,12 @@
   void DoTestOnMessageLoop() override {
     // Move the mouse to the first folder on the bookmark bar and press the
     // mouse.
-    views::LabelButton* button = GetBookmarkButton(0);
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest10::Step2));
+    OpenMenuByClick(GetBookmarkButton(0),
+                    CreateEventTask(this, &BookmarkBarViewTest10::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
     // Send a down event, which should select the first item.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
         window()->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
@@ -1099,11 +1051,9 @@
   }
 
   void Step3() {
-    // Make sure menu is showing and item is selected.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-    ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
+    ASSERT_TRUE(MenuIsShowing());
+    ASSERT_TRUE(
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
 
     // Send a key down event, which should select the next item.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
@@ -1112,11 +1062,10 @@
   }
 
   void Step4() {
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-    ASSERT_FALSE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
-    ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(1)->IsSelected());
+    ASSERT_TRUE(MenuIsShowing());
+    views::SubmenuView* submenu = bb_view_->GetMenu()->GetSubmenu();
+    ASSERT_FALSE(submenu->GetMenuItemAt(0)->IsSelected());
+    ASSERT_TRUE(submenu->GetMenuItemAt(1)->IsSelected());
 
     // Send a right arrow to force the menu to open.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
@@ -1125,14 +1074,11 @@
   }
 
   void Step5() {
-    // Make sure the submenu is showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-    views::MenuItemView* submenu = menu->GetSubmenu()->GetMenuItemAt(1);
-    ASSERT_TRUE(submenu->IsSelected());
-    ASSERT_TRUE(submenu->GetSubmenu());
-    ASSERT_TRUE(submenu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing());
+    views::MenuItemView* menu_item =
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
+    ASSERT_TRUE(menu_item->IsSelected());
+    ASSERT_TRUE(MenuIsShowing(menu_item));
 
     // Send a left arrow to close the submenu.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
@@ -1141,13 +1087,11 @@
   }
 
   void Step6() {
-    // Make sure the submenu is showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-    views::MenuItemView* submenu = menu->GetSubmenu()->GetMenuItemAt(1);
-    ASSERT_TRUE(submenu->IsSelected());
-    ASSERT_TRUE(!submenu->GetSubmenu() || !submenu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing());
+    views::MenuItemView* menu_item =
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
+    ASSERT_TRUE(menu_item->IsSelected());
+    ASSERT_FALSE(MenuIsShowing(menu_item));
 
     // Send a down arrow to go down to f1b.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
@@ -1156,11 +1100,9 @@
   }
 
   void Step7() {
-    // Make sure menu is showing and item is selected.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-    ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(2)->IsSelected());
+    ASSERT_TRUE(MenuIsShowing());
+    ASSERT_TRUE(
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(2)->IsSelected());
 
     // Send a down arrow to wrap back to f1a.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
@@ -1169,11 +1111,9 @@
   }
 
   void Step8() {
-    // Make sure menu is showing and item is selected.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-    ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
+    ASSERT_TRUE(MenuIsShowing());
+    ASSERT_TRUE(
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
 
     // Send enter, which should select the item.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
@@ -1204,28 +1144,20 @@
 class BookmarkBarViewTest11 : public BookmarkBarViewEventTestBase {
  public:
   BookmarkBarViewTest11()
-      : observer_(CreateEventTask(this, &BookmarkBarViewTest11::Step3)) {
-  }
+      : observer_(CreateEventTask(this, &BookmarkBarViewTest11::Step3)) {}
 
  protected:
   void DoTestOnMessageLoop() override {
-    // Move the mouse to the first folder on the bookmark bar and press the
-    // mouse.
-    views::LabelButton* button = bb_view_->all_bookmarks_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest11::Step2));
+    // Move the mouse to the "All Bookmarks" button and press the mouse.
+    OpenMenuByClick(bb_view_->all_bookmarks_button(),
+                    CreateEventTask(this, &BookmarkBarViewTest11::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
-    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(1);
-    ASSERT_TRUE(child_menu != nullptr);
+    views::MenuItemView* child_menu =
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
+    ASSERT_NE(nullptr, child_menu);
 
     // Right click on the first child to get its context menu.
     ui_test_utils::MoveMouseToCenterAndPress(
@@ -1242,14 +1174,8 @@
   }
 
   void Step4() {
-    // Make sure the context menu is no longer showing.
-    views::MenuItemView* menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(!menu || !menu->GetSubmenu() ||
-                !menu->GetSubmenu()->IsShowing());
-
-    // But the menu should be showing.
-    menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu && menu->GetSubmenu() && menu->GetSubmenu()->IsShowing());
+    ASSERT_FALSE(MenuIsShowing(bb_view_->GetContextMenu()));
+    ASSERT_TRUE(MenuIsShowing());
 
     // Now click on empty space.
     gfx::Point mouse_loc;
@@ -1261,18 +1187,15 @@
   }
 
   void Step5() {
-    // Make sure the menu is not showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(!menu || !menu->GetSubmenu() ||
-                !menu->GetSubmenu()->IsShowing());
+    ASSERT_FALSE(MenuIsShowing());
     Done();
   }
 
   BookmarkContextMenuNotificationObserver observer_;
 };
 
-#if BUILDFLAG(IS_CHROMEOS)  // Fails on latest versions of ChromeOS.
-                            // crbug/1483505
+// TODO(crbug.com/1483505): Fails on latest versions of ChromeOS.
+#if BUILDFLAG(IS_CHROMEOS)
 #define MAYBE_CloseMenuAfterClosingContextMenu \
   DISABLED_CloseMenuAfterClosingContextMenu
 #else
@@ -1284,46 +1207,30 @@
 class BookmarkBarViewTest12 : public BookmarkBarViewEventTestBase {
  protected:
   void DoTestOnMessageLoop() override {
-    // Open up the other folder.
-    views::LabelButton* button = bb_view_->all_bookmarks_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest12::Step2));
-    chrome::kNumBookmarkUrlsBeforePrompting = 1;
-  }
-
-  ~BookmarkBarViewTest12() override {
-    chrome::kNumBookmarkUrlsBeforePrompting = 15;
+    // Open up the "All Bookmarks" folder.
+    OpenMenuByClick(bb_view_->all_bookmarks_button(),
+                    CreateEventTask(this, &BookmarkBarViewTest12::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
-    views::MenuItemView* child_menu =
-        menu->GetSubmenu()->GetMenuItemAt(1);
-    ASSERT_TRUE(child_menu != nullptr);
-
     // Right click on the second child (a folder) to get its context menu.
-    ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
-        ui_controls::DOWN | ui_controls::UP,
+    views::MenuItemView* child_menu =
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
+    ASSERT_NE(nullptr, child_menu);
+    ui_test_utils::MoveMouseToCenterAndPress(
+        child_menu, ui_controls::RIGHT, ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest12::Step3));
   }
 
   void Step3() {
-    // Make sure the context menu is showing.
-    views::MenuItemView* menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(menu);
-    ASSERT_TRUE(menu->GetSubmenu());
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
+    ASSERT_TRUE(MenuIsShowing(context_menu));
 
     // Select the first item in the context menu (open all).
     views::MenuItemView* child_menu =
-        menu->GetSubmenu()->GetMenuItemAt(0);
-    ASSERT_TRUE(child_menu != nullptr);
+        context_menu->GetSubmenu()->GetMenuItemAt(0);
+    ASSERT_NE(nullptr, child_menu);
 
     // Click and wait until the dialog box appears.
     auto dialog_waiter = std::make_unique<DialogWaiter>();
@@ -1361,6 +1268,9 @@
     waiter.WaitForDialogClose();
     Done();
   }
+
+  base::AutoReset<size_t> prompt_immediately_resetter_{
+      &chrome::kNumBookmarkUrlsBeforePrompting, 1};
 };
 
 VIEW_TEST(BookmarkBarViewTest12, CloseWithModalDialog)
@@ -1370,28 +1280,20 @@
 class BookmarkBarViewTest13 : public BookmarkBarViewEventTestBase {
  public:
   BookmarkBarViewTest13()
-      : observer_(CreateEventTask(this, &BookmarkBarViewTest13::Step3)) {
-  }
+      : observer_(CreateEventTask(this, &BookmarkBarViewTest13::Step3)) {}
 
  protected:
   void DoTestOnMessageLoop() override {
-    // Move the mouse to the first folder on the bookmark bar and press the
-    // mouse.
-    views::LabelButton* button = bb_view_->all_bookmarks_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest13::Step2));
+    // Move the mouse to the "All Bookmarks" button and press the mouse.
+    OpenMenuByClick(bb_view_->all_bookmarks_button(),
+                    CreateEventTask(this, &BookmarkBarViewTest13::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
-    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(1);
-    ASSERT_TRUE(child_menu != nullptr);
+    views::MenuItemView* child_menu =
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
+    ASSERT_NE(nullptr, child_menu);
 
     // Right click on the first child to get its context menu.
     ui_test_utils::MoveMouseToCenterAndPress(
@@ -1401,14 +1303,11 @@
   }
 
   void Step3() {
-    // Make sure the context menu is showing.
-    views::MenuItemView* menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu());
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
+    ASSERT_TRUE(MenuIsShowing(context_menu));
 
     // Find the first separator.
-    views::SubmenuView* submenu = menu->GetSubmenu();
+    views::SubmenuView* submenu = context_menu->GetSubmenu();
     const auto i = base::ranges::find_if_not(
         submenu->children(), views::IsViewClass<views::MenuItemView>);
     ASSERT_FALSE(i == submenu->children().end());
@@ -1421,21 +1320,14 @@
   }
 
   void Step4() {
-    // The context menu should still be showing.
-    views::MenuItemView* menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu());
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
+    ASSERT_TRUE(MenuIsShowing(context_menu));
 
     // Select the first context menu item.
     ui_test_utils::MoveMouseToCenterAndPress(
-        menu->GetSubmenu()->GetMenuItemAt(1), ui_controls::LEFT,
+        context_menu->GetSubmenu()->GetMenuItemAt(1), ui_controls::LEFT,
         ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest13::Step5));
-  }
-
-  void Step5() {
-    Done();
+        base::BindOnce(&ViewEventTestBase::Done, base::Unretained(this)));
   }
 
   BookmarkContextMenuNotificationObserver observer_;
@@ -1448,8 +1340,7 @@
 class BookmarkBarViewTest14 : public BookmarkBarViewEventTestBase {
  public:
   BookmarkBarViewTest14()
-      : observer_(CreateEventTask(this, &BookmarkBarViewTest14::Step2)) {
-  }
+      : observer_(CreateEventTask(this, &BookmarkBarViewTest14::Step2)) {}
 
  protected:
   void DoTestOnMessageLoop() override {
@@ -1464,18 +1355,13 @@
 
  private:
   void Step2() {
-    // Menu should NOT be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu == nullptr);
+    ASSERT_FALSE(MenuIsShowing());
 
     // Send escape so that the context menu hides.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
         window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false, false,
-        false, CreateEventTask(this, &BookmarkBarViewTest14::Step3)));
-  }
-
-  void Step3() {
-    Done();
+        false,
+        base::BindOnce(&ViewEventTestBase::Done, base::Unretained(this))));
   }
 
   BookmarkContextMenuNotificationObserver observer_;
@@ -1488,28 +1374,20 @@
  public:
   BookmarkBarViewTest15()
       : deleted_menu_id_(0),
-        observer_(CreateEventTask(this, &BookmarkBarViewTest15::Step3)) {
-  }
+        observer_(CreateEventTask(this, &BookmarkBarViewTest15::Step3)) {}
 
  protected:
   void DoTestOnMessageLoop() override {
-    // Show the other bookmarks.
-    views::LabelButton* button = bb_view_->all_bookmarks_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest15::Step2));
+    // Show the "All Bookmarks" folder.
+    OpenMenuByClick(bb_view_->all_bookmarks_button(),
+                    CreateEventTask(this, &BookmarkBarViewTest15::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
     views::MenuItemView* child_menu =
-        menu->GetSubmenu()->GetMenuItemAt(1);
-    ASSERT_TRUE(child_menu != nullptr);
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
+    ASSERT_NE(nullptr, child_menu);
 
     deleted_menu_id_ = child_menu->GetCommand();
 
@@ -1522,37 +1400,28 @@
 
   void Step3() {
     // Make sure the context menu is showing.
-    views::MenuItemView* menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu());
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
+    ASSERT_TRUE(MenuIsShowing(context_menu));
 
     views::MenuItemView* delete_menu =
-        menu->GetMenuItemByID(IDC_BOOKMARK_BAR_REMOVE);
+        context_menu->GetMenuItemByID(IDC_BOOKMARK_BAR_REMOVE);
     ASSERT_TRUE(delete_menu);
 
     // Click on the delete button.
-    ui_test_utils::MoveMouseToCenterAndPress(delete_menu,
-        ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
+    ui_test_utils::MoveMouseToCenterAndPress(
+        delete_menu, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest15::Step4));
   }
 
   void Step4() {
-    // The context menu should not be showing.
-    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(context_menu == nullptr);
+    ASSERT_FALSE(MenuIsShowing(bb_view_->GetContextMenu()));
+    ASSERT_TRUE(MenuIsShowing());
 
-    // But the menu should be showing.
+    // The deleted_menu_id_ should have been removed.
     views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    ASSERT_EQ(nullptr, menu->GetMenuItemByID(deleted_menu_id_));
 
-    // And the deleted_menu_id_ should have been removed.
-    ASSERT_TRUE(menu->GetMenuItemByID(deleted_menu_id_) == nullptr);
-
-    bb_view_->GetMenu()->GetMenuController()->Cancel(
-        views::MenuController::ExitType::kAll);
-
+    menu->GetMenuController()->Cancel(views::MenuController::ExitType::kAll);
     Done();
   }
 
@@ -1568,22 +1437,14 @@
   void DoTestOnMessageLoop() override {
     // Move the mouse to the first folder on the bookmark bar and press the
     // mouse.
-    views::LabelButton* button = GetBookmarkButton(0);
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest16::Step2));
+    OpenMenuByClick(GetBookmarkButton(0),
+                    CreateEventTask(this, &BookmarkBarViewTest16::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
     // Button should be depressed.
-    views::LabelButton* button = GetBookmarkButton(0);
-    ASSERT_TRUE(button->GetState() == views::Button::STATE_PRESSED);
+    ASSERT_EQ(views::Button::STATE_PRESSED, GetBookmarkButton(0)->GetState());
 
     // Close the window.
     window()->Close();
@@ -1605,24 +1466,18 @@
 
  protected:
   void DoTestOnMessageLoop() override {
-    // Move the mouse to the other folder on the bookmark bar and press the
-    // left mouse button.
-    views::LabelButton* button = bb_view_->all_bookmarks_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest17::Step2));
+    // Move the mouse to the "All Bookmarks" button and press the left mouse
+    // button.
+    OpenMenuByClick(bb_view_->all_bookmarks_button(),
+                    CreateEventTask(this, &BookmarkBarViewTest17::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
     // Right click on the second item to show its context menu.
-    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(3);
-    ASSERT_TRUE(child_menu != nullptr);
+    views::MenuItemView* child_menu =
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(3);
+    ASSERT_NE(nullptr, child_menu);
     ui_test_utils::MoveMouseToCenterAndPress(
         child_menu, ui_controls::RIGHT, ui_controls::DOWN | ui_controls::UP,
         base::OnceClosure());
@@ -1630,18 +1485,14 @@
   }
 
   void Step3() {
-    // Make sure the context menu is showing.
+    ASSERT_TRUE(MenuIsShowing());
     views::MenuItemView* context_menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(context_menu != nullptr);
-    ASSERT_TRUE(context_menu->GetSubmenu());
-    ASSERT_TRUE(context_menu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing(context_menu));
 
     // Right click on the first menu item to trigger its context menu.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
-    ASSERT_TRUE(child_menu != nullptr);
+    views::MenuItemView* child_menu =
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(2);
+    ASSERT_NE(nullptr, child_menu);
 
     // The context menu and child_menu can be overlapped, calculate the
     // non-intersected Rect of the child menu and click on its center to make
@@ -1659,26 +1510,19 @@
   }
 
   void Step4() {
-    // The context menu should still be showing.
-    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(context_menu != nullptr);
-
-    // And the menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing());
+    ASSERT_TRUE(MenuIsShowing(bb_view_->GetContextMenu()));
 
     bb_view_->GetMenu()->GetMenuController()->Cancel(
         views::MenuController::ExitType::kAll);
-
     Done();
   }
 
   std::unique_ptr<BookmarkContextMenuNotificationObserver> observer_;
 };
 
-#if BUILDFLAG(IS_CHROMEOS)  // Fails on latest versions of ChromeOS.
-                            // crbug/1483505
+// TODO(crbug.com/1483505): Fails on latest versions of ChromeOS.
+#if BUILDFLAG(IS_CHROMEOS)
 #define MAYBE_ContextMenus3 DISABLED_ContextMenus3
 #else
 #define MAYBE_ContextMenus3 ContextMenus3
@@ -1691,20 +1535,13 @@
 class BookmarkBarViewTest18 : public BookmarkBarViewEventTestBase {
  protected:
   void DoTestOnMessageLoop() override {
-    // Move the mouse to the other folder on the bookmark bar and press the
-    // left mouse button.
-    views::LabelButton* button = bb_view_->all_bookmarks_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest18::Step2));
+    // Move the mouse to the "All Bookmarks" button and press the mouse.
+    OpenMenuByClick(bb_view_->all_bookmarks_button(),
+                    CreateEventTask(this, &BookmarkBarViewTest18::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
     // The button should be pressed.
     EXPECT_EQ(views::Button::STATE_PRESSED,
               bb_view_->all_bookmarks_button()->GetState());
@@ -1719,10 +1556,7 @@
   }
 
   void Step3() {
-    // Make sure the menu is showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing());
 
     // The menu for the first folder should be in the pressed state (since the
     // menu is showing for it)...
@@ -1731,8 +1565,8 @@
     EXPECT_EQ(views::Button::STATE_NORMAL,
               bb_view_->all_bookmarks_button()->GetState());
 
-    menu->GetMenuController()->Cancel(views::MenuController::ExitType::kAll);
-
+    bb_view_->GetMenu()->GetMenuController()->Cancel(
+        views::MenuController::ExitType::kAll);
     Done();
   }
 };
@@ -1744,35 +1578,24 @@
 class BookmarkBarViewTest19 : public BookmarkBarViewEventTestBase {
  protected:
   void DoTestOnMessageLoop() override {
-    // Move the mouse to the other folder on the bookmark bar and press the
-    // left mouse button.
-    views::LabelButton* button = bb_view_->all_bookmarks_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest19::Step2));
+    // Move the mouse to the "All Bookmarks" button and press the mouse.
+    OpenMenuByClick(bb_view_->all_bookmarks_button(),
+                    CreateEventTask(this, &BookmarkBarViewTest19::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
     // Click on the first folder.
-    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
-    ASSERT_TRUE(child_menu != nullptr);
+    views::MenuItemView* child_menu =
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(2);
+    ASSERT_NE(nullptr, child_menu);
     ui_test_utils::MoveMouseToCenterAndPress(
-        child_menu, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
+        child_menu, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest19::Step3));
   }
 
   void Step3() {
-    // Make sure the menu is showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing());
 
     // Move the mouse back to the "All Bookmarks" button.
     views::LabelButton* button = bb_view_->all_bookmarks_button();
@@ -1784,29 +1607,22 @@
   }
 
   void Step4() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing());
 
     // Click on the first folder.
-    views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
-    ASSERT_TRUE(child_menu != nullptr);
+    views::MenuItemView* child_menu =
+        bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(2);
+    ASSERT_NE(nullptr, child_menu);
     ui_test_utils::MoveMouseToCenterAndPress(
-        child_menu,
-        ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
+        child_menu, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest19::Step5));
   }
 
   void Step5() {
-    // Make sure the menu is showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing());
 
-    menu->GetMenuController()->Cancel(views::MenuController::ExitType::kAll);
-
+    bb_view_->GetMenu()->GetMenuController()->Cancel(
+        views::MenuController::ExitType::kAll);
     Done();
   }
 };
@@ -1857,17 +1673,12 @@
 
     // Move the mouse to the first folder on the bookmark bar and press the
     // left mouse button.
-    ui_test_utils::MoveMouseToCenterAndPress(
-        GetBookmarkButton(0), ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest20::Step2));
+    OpenMenuByClick(GetBookmarkButton(0),
+                    CreateEventTask(this, &BookmarkBarViewTest20::Step2));
   }
 
   void Step2() {
     EXPECT_EQ(1, test_view_->press_count());
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_NE(nullptr, menu);
-    EXPECT_TRUE(menu->GetSubmenu()->IsShowing());
 
     // Move the mouse to the Test View and press the left mouse button.
     // The context menu will consume the event and exit. Thereafter,
@@ -1879,11 +1690,8 @@
   }
 
   void Step3() {
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-    EXPECT_EQ(1, test_view_->press_count());
-#else
-    EXPECT_EQ(2, test_view_->press_count());
-#endif
+    EXPECT_EQ(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ? 1 : 2,
+              test_view_->press_count());
     EXPECT_EQ(nullptr, bb_view_->GetMenu());
     Done();
   }
@@ -1917,28 +1725,20 @@
 class BookmarkBarViewTest21 : public BookmarkBarViewEventTestBase {
  public:
   BookmarkBarViewTest21()
-      : observer_(CreateEventTask(this, &BookmarkBarViewTest21::Step3)) {
-  }
+      : observer_(CreateEventTask(this, &BookmarkBarViewTest21::Step3)) {}
 
  protected:
   // Move the mouse to the empty folder on the bookmark bar and press the
   // left mouse button.
   void DoTestOnMessageLoop() override {
-    views::LabelButton* button = GetBookmarkButton(5);
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest21::Step2));
+    OpenMenuByClick(GetBookmarkButton(5),
+                    CreateEventTask(this, &BookmarkBarViewTest21::Step2));
   }
 
  private:
   // Confirm that a menu for empty folder shows and right click the menu.
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu != nullptr);
-
-    views::SubmenuView* submenu = menu->GetSubmenu();
-    ASSERT_TRUE(submenu->IsShowing());
+    views::SubmenuView* submenu = bb_view_->GetMenu()->GetSubmenu();
     ASSERT_EQ(1u, submenu->children().size());
 
     auto* empty_item =
@@ -1954,19 +1754,16 @@
 
   // Confirm that context menu shows and click REMOVE menu.
   void Step3() {
-    // Make sure the context menu is showing.
-    views::MenuItemView* menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(menu != nullptr);
-    ASSERT_TRUE(menu->GetSubmenu());
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
+    ASSERT_TRUE(MenuIsShowing(context_menu));
 
     views::MenuItemView* delete_menu =
-        menu->GetMenuItemByID(IDC_BOOKMARK_BAR_REMOVE);
+        context_menu->GetMenuItemByID(IDC_BOOKMARK_BAR_REMOVE);
     ASSERT_TRUE(delete_menu);
 
     // Click on the delete menu item.
-    ui_test_utils::MoveMouseToCenterAndPress(delete_menu,
-        ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
+    ui_test_utils::MoveMouseToCenterAndPress(
+        delete_menu, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest21::Step4));
   }
 
@@ -1975,9 +1772,8 @@
     views::LabelButton* button = GetBookmarkButton(5);
     ASSERT_TRUE(button);
     EXPECT_EQ(u"d", button->GetText());
-    EXPECT_TRUE(bb_view_->GetContextMenu() == nullptr);
-    EXPECT_TRUE(bb_view_->GetMenu() == nullptr);
-
+    EXPECT_FALSE(MenuIsShowing());
+    EXPECT_FALSE(MenuIsShowing(bb_view_->GetContextMenu()));
     Done();
   }
 
@@ -2037,21 +1833,13 @@
 
  protected:
   void DoTestOnMessageLoop() override {
-    // Move the mouse to the first folder on the bookmark bar and press the
-    // mouse.
-    views::LabelButton* button = bb_view_->all_bookmarks_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest23::Step2));
+    // Move the mouse to the "All Bookmarks" button and press the mouse.
+    OpenMenuByClick(bb_view_->all_bookmarks_button(),
+                    CreateEventTask(this, &BookmarkBarViewTest23::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
     // Navigate down to highlight the first menu item.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
         window()->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
@@ -2059,10 +1847,7 @@
   }
 
   void Step3() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing());
 
     // Navigate down to highlight the second menu item.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
@@ -2071,10 +1856,7 @@
   }
 
   void Step4() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing());
 
     // Open the context menu via the keyboard.
     ASSERT_TRUE(ui_controls::SendKeyPress(window()->GetNativeWindow(),
@@ -2084,15 +1866,12 @@
   }
 
   void Step5() {
-    // Make sure the context menu is showing.
-    views::MenuItemView* menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(menu);
-    ASSERT_TRUE(menu->GetSubmenu());
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    views::MenuItemView* context_menu = bb_view_->GetContextMenu();
+    ASSERT_TRUE(MenuIsShowing(context_menu));
 
     // Select the first menu item (open).
     ui_test_utils::MoveMouseToCenterAndPress(
-        menu->GetSubmenu()->GetMenuItemAt(1), ui_controls::LEFT,
+        context_menu->GetSubmenu()->GetMenuItemAt(1), ui_controls::LEFT,
         ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest23::Step6));
   }
@@ -2124,21 +1903,13 @@
 
  protected:
   void DoTestOnMessageLoop() override {
-    // Move the mouse to the first folder on the bookmark bar and press the
-    // mouse.
-    views::LabelButton* button = bb_view_->all_bookmarks_button();
-    ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
-        ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest24::Step2));
+    // Move the mouse to the "All Bookmarks" button and press the mouse.
+    OpenMenuByClick(bb_view_->all_bookmarks_button(),
+                    CreateEventTask(this, &BookmarkBarViewTest24::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
     // Navigate down to highlight the first menu item.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
         window()->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
@@ -2146,10 +1917,7 @@
   }
 
   void Step3() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing());
 
     // Open the context menu via the keyboard.
     ASSERT_TRUE(ui_controls::SendKeyPress(window()->GetNativeWindow(),
@@ -2159,11 +1927,7 @@
   }
 
   void Step4() {
-    // Make sure the context menu is showing.
-    views::MenuItemView* menu = bb_view_->GetContextMenu();
-    ASSERT_TRUE(menu);
-    ASSERT_TRUE(menu->GetSubmenu());
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    ASSERT_TRUE(MenuIsShowing(bb_view_->GetContextMenu()));
 
     // Send escape to close the context menu.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
@@ -2172,13 +1936,8 @@
   }
 
   void Step5() {
-    // The context menu should be closed but the parent menu should still be
-    // showing.
-    ASSERT_FALSE(bb_view_->GetContextMenu());
-
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
+    ASSERT_FALSE(MenuIsShowing(bb_view_->GetContextMenu()));
+    ASSERT_TRUE(MenuIsShowing());
 
     // Send escape to close the main menu.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
@@ -2201,19 +1960,12 @@
   void DoTestOnMessageLoop() override {
     // Move the mouse to the first folder on the bookmark bar and press the
     // mouse.
-    views::LabelButton* button = GetBookmarkButton(0);
-    ui_test_utils::MoveMouseToCenterAndPress(
-        button, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest25::Step2));
+    OpenMenuByClick(GetBookmarkButton(0),
+                    CreateEventTask(this, &BookmarkBarViewTest25::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
     // Send KEYCODE key event, which should close the menu.
     ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
         window()->GetNativeWindow(), KEYCODE, false, false, false, false,
@@ -2221,10 +1973,7 @@
   }
 
   void Step3() {
-    // Make sure menu is not showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu == nullptr);
-
+    ASSERT_FALSE(MenuIsShowing());
     Done();
   }
 };
@@ -2243,19 +1992,12 @@
   void DoTestOnMessageLoop() override {
     // Move the mouse to the first folder on the bookmark bar and press the
     // mouse.
-    views::LabelButton* button = GetBookmarkButton(0);
-    ui_test_utils::MoveMouseToCenterAndPress(
-        button, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
-        CreateEventTask(this, &BookmarkBarViewTest26::Step2));
+    OpenMenuByClick(GetBookmarkButton(0),
+                    CreateEventTask(this, &BookmarkBarViewTest26::Step2));
   }
 
  private:
   void Step2() {
-    // Menu should be showing.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu);
-    ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
-
     // Send WM_CANCELMODE, which should close the menu. The message is sent
     // synchronously, however, we post a task to make sure that the message is
     // processed completely before finishing the test.
@@ -2268,10 +2010,7 @@
   }
 
   void Step3() {
-    // Menu should not be showing anymore.
-    views::MenuItemView* menu = bb_view_->GetMenu();
-    ASSERT_TRUE(menu == nullptr);
-
+    ASSERT_FALSE(MenuIsShowing());
     Done();
   }
 };
@@ -2305,11 +2044,8 @@
 
 class BookmarkBarViewTest28 : public BookmarkBarViewEventTestBase {
  protected:
-#if BUILDFLAG(IS_MAC)
-  const ui_controls::AcceleratorState kAccelatorState = ui_controls::kCommand;
-#else
-  const ui_controls::AcceleratorState kAccelatorState = ui_controls::kControl;
-#endif  // BUILDFLAG(IS_MAC)
+  static constexpr ui_controls::AcceleratorState kAccelatorState =
+      BUILDFLAG(IS_MAC) ? ui_controls::kCommand : ui_controls::kControl;
 
   void DoTestOnMessageLoop() override {
     views::LabelButton* button = GetBookmarkButton(0);
@@ -2347,9 +2083,8 @@
   void OnDropMenuShown() override {
     // The folder's menu should be open, showing an "(empty)" placeholder.
     views::MenuItemView* drop_menu = bb_view_->GetDropMenu();
-    ASSERT_NE(nullptr, drop_menu);
+    ASSERT_TRUE(MenuIsShowing(drop_menu));
     views::SubmenuView* drop_submenu = drop_menu->GetSubmenu();
-    ASSERT_TRUE(drop_submenu->IsShowing());
     ASSERT_FALSE(drop_submenu->children().empty());
     const views::View* target_view = drop_submenu->children().front();
     EXPECT_TRUE(views::IsViewClass<views::EmptyMenuMenuItem>(target_view));
diff --git a/chrome/browser/ui/views/enable_link_capturing_infobar_browsertest.cc b/chrome/browser/ui/views/enable_link_capturing_infobar_browsertest.cc
index 3c4cb7b..f247dce 100644
--- a/chrome/browser/ui/views/enable_link_capturing_infobar_browsertest.cc
+++ b/chrome/browser/ui/views/enable_link_capturing_infobar_browsertest.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/apps/link_capturing/enable_link_capturing_infobar_delegate.h"
 #include "chrome/browser/apps/link_capturing/intent_picker_info.h"
 #include "chrome/browser/apps/link_capturing/link_capturing_feature_test_support.h"
-#include "chrome/browser/apps/link_capturing/link_capturing_features.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
@@ -29,6 +28,7 @@
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/infobars/content/content_infobar_manager.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
@@ -70,13 +70,18 @@
 };
 
 class EnableLinkCapturingInfobarBrowserTest
-    : public WebAppNavigationBrowserTest {
+    : public WebAppNavigationBrowserTest,
+      public testing::WithParamInterface<bool> {
  public:
   EnableLinkCapturingInfobarBrowserTest() {
     feature_list_.InitWithFeaturesAndParameters(
-        apps::test::GetFeaturesToEnableLinkCapturingUX(), {});
+        apps::test::GetFeaturesToEnableLinkCapturingUX(
+            /*override_captures_by_default=*/GetParam()),
+        {});
   }
 
+  bool LinkCapturingEnabledByDefault() { return GetParam(); }
+
   IntentChipButton* GetIntentPickerIcon() {
     return BrowserView::GetBrowserViewForBrowser(browser())
         ->toolbar_button_provider()
@@ -131,10 +136,17 @@
   }
 
   void TurnOnLinkCapturing(webapps::AppId app_id) {
-    ScopedRegistryUpdate update = provider().sync_bridge_unsafe().BeginUpdate();
-    WebApp* app = update->UpdateApp(app_id);
-    CHECK(app);
-    app->SetIsUserSelectedAppForSupportedLinks(true);
+    base::test::TestFuture<void> preference_set;
+    provider().scheduler().SetAppCapturesSupportedLinksDisableOverlapping(
+        app_id, /*set_to_preferred=*/true, preference_set.GetCallback());
+    ASSERT_TRUE(preference_set.Wait());
+  }
+
+  void TurnOffLinkCapturing(webapps::AppId app_id) {
+    base::test::TestFuture<void> preference_set;
+    provider().scheduler().SetAppCapturesSupportedLinksDisableOverlapping(
+        app_id, /*set_to_preferred=*/false, preference_set.GetCallback());
+    ASSERT_TRUE(preference_set.Wait());
   }
 
   testing::AssertionResult WaitForIntentPickerToShow() {
@@ -223,10 +235,16 @@
   base::test::ScopedFeatureList feature_list_;
 };
 
-IN_PROC_BROWSER_TEST_F(EnableLinkCapturingInfobarBrowserTest,
+IN_PROC_BROWSER_TEST_P(EnableLinkCapturingInfobarBrowserTest,
                        InfoBarShowsOnIntentPickerLaunch) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  const auto [_, in_scope_url] = InstallTestApp();
+  const auto [app_id, in_scope_url] = InstallTestApp();
+
+  // The infobar shows up only when link capturing is not enabled for an app.
+  // For default-on behavior, switch off link capturing manually.
+  if (LinkCapturingEnabledByDefault()) {
+    TurnOffLinkCapturing(app_id);
+  }
 
   NavigateViaLinkClick(browser(), in_scope_url);
 
@@ -239,11 +257,17 @@
   EXPECT_NE(GetLinkCapturingInfoBar(app_browser), nullptr);
 }
 
-IN_PROC_BROWSER_TEST_F(EnableLinkCapturingInfobarBrowserTest,
+IN_PROC_BROWSER_TEST_P(EnableLinkCapturingInfobarBrowserTest,
                        EnableLinkCapturingThroughInfoBar) {
   ASSERT_TRUE(embedded_test_server()->Start());
   const auto [app_id, in_scope_url] = InstallTestApp();
 
+  // The infobar shows up only when link capturing is not enabled for an app.
+  // For default-on behavior, switch off link capturing manually.
+  if (LinkCapturingEnabledByDefault()) {
+    TurnOffLinkCapturing(app_id);
+  }
+
   NavigateViaLinkClick(browser(), in_scope_url);
 
   Browser* app_browser;
@@ -273,11 +297,16 @@
                 in_scope_url));
 }
 
-IN_PROC_BROWSER_TEST_F(EnableLinkCapturingInfobarBrowserTest,
+IN_PROC_BROWSER_TEST_P(EnableLinkCapturingInfobarBrowserTest,
                        InfoBarNotShownOnLinkCapturingEnabled) {
   ASSERT_TRUE(embedded_test_server()->Start());
   const auto [app_id, in_scope_url] = InstallTestApp();
-  TurnOnLinkCapturing(app_id);
+
+  // The infobar shows up only when link capturing is not enabled for an app.
+  // For default-on behavior, switch off link capturing manually.
+  if (!LinkCapturingEnabledByDefault()) {
+    TurnOnLinkCapturing(app_id);
+  }
 
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), in_scope_url));
 
@@ -294,10 +323,16 @@
   EXPECT_EQ(GetLinkCapturingInfoBar(app_browser), nullptr);
 }
 
-IN_PROC_BROWSER_TEST_F(EnableLinkCapturingInfobarBrowserTest,
+IN_PROC_BROWSER_TEST_P(EnableLinkCapturingInfobarBrowserTest,
                        RecordUserActionCancelled) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  const auto [_, in_scope_url] = InstallTestApp();
+  const auto [app_id, in_scope_url] = InstallTestApp();
+
+  // The infobar shows up only when link capturing is not enabled for an app.
+  // For default-on behavior, switch off link capturing manually.
+  if (LinkCapturingEnabledByDefault()) {
+    TurnOffLinkCapturing(app_id);
+  }
 
   NavigateViaLinkClick(browser(), in_scope_url);
 
@@ -326,10 +361,16 @@
                 in_scope_url));
 }
 
-IN_PROC_BROWSER_TEST_F(EnableLinkCapturingInfobarBrowserTest,
+IN_PROC_BROWSER_TEST_P(EnableLinkCapturingInfobarBrowserTest,
                        RecordUserActionIgnored) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  const auto [_, in_scope_url] = InstallTestApp();
+  const auto [app_id, in_scope_url] = InstallTestApp();
+
+  // The infobar shows up only when link capturing is not enabled for an app.
+  // For default-on behavior, switch off link capturing manually.
+  if (LinkCapturingEnabledByDefault()) {
+    TurnOffLinkCapturing(app_id);
+  }
 
   NavigateViaLinkClick(browser(), in_scope_url);
 
@@ -355,10 +396,16 @@
                 in_scope_url));
 }
 
-IN_PROC_BROWSER_TEST_F(EnableLinkCapturingInfobarBrowserTest, AppLaunched) {
+IN_PROC_BROWSER_TEST_P(EnableLinkCapturingInfobarBrowserTest, AppLaunched) {
   ASSERT_TRUE(embedded_test_server()->Start());
   const auto [app_id, in_scope_url] = InstallTestApp();
 
+  // The infobar shows up only when link capturing is not enabled for an app.
+  // For default-on behavior, switch off link capturing manually.
+  if (LinkCapturingEnabledByDefault()) {
+    TurnOffLinkCapturing(app_id);
+  }
+
   NavigateViaLinkClick(browser(), in_scope_url);
 
   Browser* app_browser;
@@ -372,7 +419,6 @@
 
   infobars::InfoBar* infobar = GetLinkCapturingInfoBar(app_browser);
   ASSERT_TRUE(infobar);
-  base::UserActionTester user_action_tester;
   EXPECT_TRUE(
       static_cast<ConfirmInfoBarDelegate*>(infobar->delegate())->Accept());
   // Because there is no testing utility for info bars, manually remove.
@@ -398,9 +444,15 @@
   }
 }
 
-IN_PROC_BROWSER_TEST_F(EnableLinkCapturingInfobarBrowserTest, BarRemoved) {
+IN_PROC_BROWSER_TEST_P(EnableLinkCapturingInfobarBrowserTest, BarRemoved) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  const auto [_, in_scope_url] = InstallTestApp();
+  const auto [app_id, in_scope_url] = InstallTestApp();
+
+  // The infobar shows up only when link capturing is not enabled for an app.
+  // For default-on behavior, switch off link capturing manually.
+  if (LinkCapturingEnabledByDefault()) {
+    TurnOffLinkCapturing(app_id);
+  }
 
   NavigateViaLinkClick(browser(), in_scope_url);
 
@@ -426,10 +478,16 @@
 }
 
 // TODO(https://crbug.com/1492121): Flaky on all platforms.
-IN_PROC_BROWSER_TEST_F(EnableLinkCapturingInfobarBrowserTest,
+IN_PROC_BROWSER_TEST_P(EnableLinkCapturingInfobarBrowserTest,
                        DISABLED_InfoBarHiddenAfterDismissals) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  const auto [_, in_scope_url] = InstallTestApp();
+  const auto [app_id, in_scope_url] = InstallTestApp();
+
+  // The infobar shows up only when link capturing is not enabled for an app.
+  // For default-on behavior, switch off link capturing manually.
+  if (LinkCapturingEnabledByDefault()) {
+    TurnOffLinkCapturing(app_id);
+  }
 
   // Dismiss the infobar twice.
   for (int i = 0; i < 2; ++i) {
@@ -473,12 +531,19 @@
   EXPECT_FALSE(infobar);
 }
 
-IN_PROC_BROWSER_TEST_F(EnableLinkCapturingInfobarBrowserTest,
+IN_PROC_BROWSER_TEST_P(EnableLinkCapturingInfobarBrowserTest,
                        OuterAppNoInfoBar) {
   ASSERT_TRUE(embedded_test_server()->Start());
   const auto [outer_app_id, inner_app_id, inner_app_scoped_url] =
       InstallOuterAppAndInnerApp();
 
+  // The infobar shows up only when link capturing is not enabled for an app.
+  // For default-on behavior, switch off link capturing manually.
+  if (LinkCapturingEnabledByDefault()) {
+    TurnOffLinkCapturing(outer_app_id);
+    TurnOffLinkCapturing(inner_app_id);
+  }
+
   NavigateViaLinkClick(browser(), inner_app_scoped_url);
   EXPECT_TRUE(ClickIntentPickerAndWaitForBubble());
 
@@ -505,5 +570,12 @@
   EXPECT_FALSE(GetLinkCapturingInfoBar(app_browser));
 }
 
+INSTANTIATE_TEST_SUITE_P(,
+                         EnableLinkCapturingInfobarBrowserTest,
+                         testing::Values(true, false),
+                         [](const testing::TestParamInfo<bool>& info) {
+                           return info.param ? "DefaultOn" : "DefaultOff";
+                         });
+
 }  // namespace
 }  // namespace web_app
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc
index 019b605..4a1cc8c 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc
+++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc
@@ -23,6 +23,7 @@
 #include "components/content_settings/core/common/features.h"
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/feature_engagement/public/feature_constants.h"
+#include "components/privacy_sandbox/tracking_protection_prefs.h"
 #include "components/site_engagement/content/site_engagement_service.h"
 #include "components/user_education/views/help_bubble_view.h"
 #include "content/public/test/browser_test.h"
@@ -80,11 +81,11 @@
   }
 
  protected:
-  virtual std::vector<base::test::FeatureRef> EnabledFeatures() {
-    return {content_settings::features::kUserBypassUI};
-  }
+  virtual std::vector<base::test::FeatureRef> EnabledFeatures() { return {}; }
 
-  virtual std::vector<base::test::FeatureRef> DisabledFeatures() { return {}; }
+  virtual std::vector<base::test::FeatureRef> DisabledFeatures() {
+    return {content_settings::features::kTrackingProtection3pcd};
+  }
 
   auto CheckIcon(ElementSpecifier view,
                  const gfx::VectorIcon& icon_pre_2023_refresh,
@@ -159,11 +160,16 @@
         .InDays();
   }
 
-  void BlockThirdPartyCookies() {
-    browser()->profile()->GetPrefs()->SetInteger(
-        prefs::kCookieControlsMode,
-        static_cast<int>(
-            content_settings::CookieControlsMode::kBlockThirdParty));
+  void BlockThirdPartyCookies(bool use_3pcd = false) {
+    if (use_3pcd) {
+      browser()->profile()->GetPrefs()->SetBoolean(
+          prefs::kTrackingProtection3pcdEnabled, true);
+    } else {
+      browser()->profile()->GetPrefs()->SetInteger(
+          prefs::kCookieControlsMode,
+          static_cast<int>(
+              content_settings::CookieControlsMode::kBlockThirdParty));
+    }
   }
 
   void BlockCookiesAndSetHighConfidenceForSite() {
@@ -306,8 +312,7 @@
 
  protected:
   std::vector<base::test::FeatureRef> EnabledFeatures() override {
-    return {content_settings::features::kUserBypassUI,
-            feature_engagement::kIPHCookieControlsFeature};
+    return {feature_engagement::kIPHCookieControlsFeature};
   }
 };
 
@@ -379,15 +384,13 @@
 
  protected:
   std::vector<base::test::FeatureRef> EnabledFeatures() override {
-    return {content_settings::features::kUserBypassUI,
-            feature_engagement::kIPH3pcdUserBypassFeature,
-            content_settings::features::kTrackingProtection3pcd};
+    return {feature_engagement::kIPH3pcdUserBypassFeature};
   }
 };
 
 IN_PROC_BROWSER_TEST_F(CookieControlsInteractiveUiWith3pcdUserBypassIphTest,
                        ShowAndHide3pcdUbIph) {
-  BlockThirdPartyCookies();
+  BlockThirdPartyCookies(/*use_3pcd=*/true);
   RunTestSequenceInContext(
       context(), ObserveState(kFeatureEngagementInitializedState, browser()),
       WaitForState(kFeatureEngagementInitializedState, true),
@@ -402,7 +405,7 @@
 
 IN_PROC_BROWSER_TEST_F(CookieControlsInteractiveUiWith3pcdUserBypassIphTest,
                        Show3pcdUbIphAndOpenCookieControlsViaIcon) {
-  BlockThirdPartyCookies();
+  BlockThirdPartyCookies(/*use_3pcd=*/true);
   RunTestSequenceInContext(
       context(), ObserveState(kFeatureEngagementInitializedState, browser()),
       WaitForState(kFeatureEngagementInitializedState, true),
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index 62b0b1e..40f7b99 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -561,6 +561,18 @@
 }
 
 void OmniboxResultView::OnMouseReleased(const ui::MouseEvent& event) {
+  if (OmniboxFieldTrial::IsKeywordModeRefreshEnabled() &&
+      match_.type == AutocompleteMatchType::STARTER_PACK) {
+    // Starter pack matches in the keyword mode refresh are a special case that
+    // does not commit the omnibox by opening a selected match.
+    OmniboxEditModel* model = popup_view_->model();
+    model->ClearKeyword();
+    model->SetPopupSelection(OmniboxPopupSelection(
+        model_index_, OmniboxPopupSelection::LineState::KEYWORD_MODE));
+    model->AcceptKeyword(metrics::OmniboxEventProto::TAB);
+    return;
+  }
+
   if (event.IsOnlyMiddleMouseButton() || event.IsOnlyLeftMouseButton()) {
     WindowOpenDisposition disposition =
         event.IsOnlyLeftMouseButton()
diff --git a/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc b/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc
index f964819..a7f5e97 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc
@@ -420,11 +420,6 @@
     const OmniboxPopupSelection selection,
     const ui::Event& event) {
   if (selection.state == OmniboxPopupSelection::KEYWORD_MODE) {
-    // TODO(yoangela): Port to PopupModel and merge with keyEvent
-    // TODO(orinj): Clear out existing suggestions, particularly this one, as
-    // once we AcceptKeyword, we are really in a new scope state and holding
-    // onto old suggestions is confusing and error prone. Without this check,
-    // a second click of the button violates assumptions in |AcceptKeyword|.
     // Note: Since keyword mode logic depends on state of the edit model, the
     // selection must first be set to prepare for keyword mode before accepting.
     popup_view_->model()->SetPopupSelection(selection);
diff --git a/chrome/browser/ui/views/performance_controls/high_efficiency_exclusion_list_browsertest.cc b/chrome/browser/ui/views/performance_controls/high_efficiency_exclusion_list_browsertest.cc
index c5030bf..417686b 100644
--- a/chrome/browser/ui/views/performance_controls/high_efficiency_exclusion_list_browsertest.cc
+++ b/chrome/browser/ui/views/performance_controls/high_efficiency_exclusion_list_browsertest.cc
@@ -146,9 +146,8 @@
   EXPECT_TRUE(NavigateAndDiscardFirstTab(GetURL(kWWWExampleURL)));
 }
 
-// crbug.com/1435375
 IN_PROC_BROWSER_TEST_F(HighEfficiencyExclusionListBrowserTest,
-                       DISABLED_ExclusionListMatchesWildCards) {
+                       ExclusionListMatchesWildCards) {
   PrefService* prefs = GetPrefs();
   base::Value::List exclude_sites_with_http_scheme;
   exclude_sites_with_http_scheme.Append("http://*");
diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
index 6150dfe4..670ec08 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
@@ -883,7 +883,7 @@
   combobox->SetBackgroundColorId(ui::kColorSidePanelComboboxBackground);
   if (features::IsChromeRefresh2023()) {
     combobox->SetForegroundColorId(kColorSidePanelEntryTitle);
-    combobox->SetForegroundIconColorId(kColorSidePanelEntryIcon);
+    combobox->SetForegroundIconColorId(kColorSidePanelComboboxEntryIcon);
     combobox->SetForegroundTextStyle(views::style::STYLE_HEADLINE_5);
   }
   combobox->SetEventHighlighting(true);
diff --git a/chrome/browser/ui/views/test/view_event_test_base.cc b/chrome/browser/ui/views/test/view_event_test_base.cc
index 632ab1b7..97420e6 100644
--- a/chrome/browser/ui/views/test/view_event_test_base.cc
+++ b/chrome/browser/ui/views/test/view_event_test_base.cc
@@ -170,6 +170,13 @@
   run_loop_.Run();
 }
 
+void ViewEventTestBase::RunTestMethod(base::OnceClosure task) {
+  std::move(task).Run();
+  if (HasFatalFailure()) {
+    Done();
+  }
+}
+
 scoped_refptr<base::SingleThreadTaskRunner>
 ViewEventTestBase::GetDragTaskRunner() {
 #if BUILDFLAG(IS_WIN)
@@ -189,9 +196,3 @@
   return base::SingleThreadTaskRunner::GetCurrentDefault();
 #endif
 }
-
-void ViewEventTestBase::RunTestMethod(base::OnceClosure task) {
-  std::move(task).Run();
-  if (HasFatalFailure())
-    Done();
-}
diff --git a/chrome/browser/ui/views/test/view_event_test_base.h b/chrome/browser/ui/views/test/view_event_test_base.h
index f928d78..df4fe57 100644
--- a/chrome/browser/ui/views/test/view_event_test_base.h
+++ b/chrome/browser/ui/views/test/view_event_test_base.h
@@ -116,16 +116,16 @@
                           base::BindOnce(method, base::Unretained(target)));
   }
 
+  // Callback from CreateEventTask. Runs the supplied task and if there are
+  // failures invokes Done.
+  void RunTestMethod(base::OnceClosure task);
+
   // Returns a task runner to use for drag-related mouse events.
   scoped_refptr<base::SingleThreadTaskRunner> GetDragTaskRunner();
 
  private:
   friend class TestBaseWidgetDelegate;
 
-  // Callback from CreateEventTask. Runs the supplied task and if there are
-  // failures invokes Done.
-  void RunTestMethod(base::OnceClosure task);
-
 #if defined(USE_AURA) && !BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<display::Screen> screen_;
 #endif
diff --git a/chrome/browser/ui/views/web_apps/isolated_web_apps/DEPS b/chrome/browser/ui/views/web_apps/isolated_web_apps/DEPS
new file mode 100644
index 0000000..4a019e48
--- /dev/null
+++ b/chrome/browser/ui/views/web_apps/isolated_web_apps/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+    "+components/web_package/signed_web_bundles",
+]
diff --git a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_model.cc b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_model.cc
index 725cee3..34da492 100644
--- a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_model.cc
+++ b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_model.cc
@@ -7,10 +7,28 @@
 #include <string>
 
 #include "base/files/file_path.h"
+#include "chrome/browser/web_applications/isolated_web_apps/signed_web_bundle_metadata.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web_app {
 
+IsolatedWebAppInstallerModel::DialogContent::DialogContent(
+    bool is_error,
+    int message,
+    int details,
+    absl::optional<LinkInfo> details_link,
+    absl::optional<int> accept_message)
+    : is_error(is_error),
+      message(message),
+      details(details),
+      details_link(details_link),
+      accept_message(accept_message) {}
+
+IsolatedWebAppInstallerModel::DialogContent::DialogContent(
+    const IsolatedWebAppInstallerModel::DialogContent&) = default;
+
+IsolatedWebAppInstallerModel::DialogContent::~DialogContent() = default;
+
 IsolatedWebAppInstallerModel::IsolatedWebAppInstallerModel(
     const base::FilePath& bundle_path)
     : bundle_path_(bundle_path), step_(Step::kDisabled) {}
diff --git a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_model.h b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_model.h
index 420f3bb..a2d2f34a 100644
--- a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_model.h
+++ b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_model.h
@@ -5,9 +5,10 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_WEB_APPS_ISOLATED_WEB_APPS_ISOLATED_WEB_APP_INSTALLER_MODEL_H_
 #define CHROME_BROWSER_UI_VIEWS_WEB_APPS_ISOLATED_WEB_APPS_ISOLATED_WEB_APP_INSTALLER_MODEL_H_
 
-#include <string>
+#include <utility>
 
 #include "base/files/file_path.h"
+#include "base/functional/callback_forward.h"
 #include "chrome/browser/web_applications/isolated_web_apps/signed_web_bundle_metadata.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -23,11 +24,22 @@
     kInstallSuccess,
   };
 
+  using LinkInfo = std::pair<int, base::RepeatingClosure>;
   struct DialogContent {
-    bool is_error = true;
-    bool is_recoverable = false;
-    int message_id = -1;
-    std::u16string details;
+    DialogContent(bool is_error,
+                  int message,
+                  int details,
+                  absl::optional<LinkInfo> details_link = absl::nullopt,
+                  absl::optional<int> accept_message = absl::nullopt);
+    DialogContent(const DialogContent&);
+    ~DialogContent();
+
+    bool is_error;
+    int message;
+    int details;
+    absl::optional<LinkInfo> details_link;
+    // Message on the non-Cancel button of the dialog, if it should be present.
+    absl::optional<int> accept_message;
   };
 
   explicit IsolatedWebAppInstallerModel(const base::FilePath& bundle_path);
@@ -43,7 +55,8 @@
   const SignedWebBundleMetadata& bundle_metadata() { return *bundle_metadata_; }
 
   void SetDialogContent(absl::optional<DialogContent> dialog_content);
-  absl::optional<DialogContent> dialog_content() { return dialog_content_; }
+  bool has_dialog_content() { return dialog_content_.has_value(); }
+  const DialogContent& dialog_content() { return dialog_content_.value(); }
 
  private:
   base::FilePath bundle_path_;
diff --git a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view.cc b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view.cc
index 1e873e9e..c094191 100644
--- a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view.cc
+++ b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view.cc
@@ -19,8 +19,13 @@
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/image_model.h"
+#include "ui/base/ui_base_types.h"
+#include "ui/color/color_id.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/range/range.h"
+#include "ui/gfx/vector_icon_types.h"
+#include "ui/strings/grit/ui_strings.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
 #include "ui/views/controls/progress_bar.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/layout/box_layout.h"
@@ -57,155 +62,133 @@
   return label;
 }
 
+ui::ImageModel CreateImageModelFromVector(const gfx::VectorIcon& vector_icon,
+                                          ui::ColorId color_id) {
+  return ui::ImageModel::FromVectorIcon(vector_icon, color_id, kIconSize);
+}
+
 }  // namespace
 
-// Base class for all installer screens that handles common UI elements like
-// icons, title, and subtitle.
-class InstallerScreenView : public views::BoxLayoutView {
+// The contents view used for all installer screens. This will handle rendering
+// common UI elements like icon, title, subtitle, and an optional View for the
+// body of the dialog.
+class InstallerDialogView : public views::BoxLayoutView {
  public:
-  METADATA_HEADER(InstallerScreenView);
+  METADATA_HEADER(InstallerDialogView);
 
-  explicit InstallerScreenView(const ui::ImageModel& icon_model) {
+  // The message_id of the link's body and a callback to run when it's clicked.
+  using LinkInfo = std::pair<int, base::RepeatingClosure>;
+
+  InstallerDialogView(const ui::ImageModel& icon_model,
+                      int title_id,
+                      int subtitle_id,
+                      absl::optional<LinkInfo> subtitle_link = absl::nullopt,
+                      std::unique_ptr<views::View> contents_view = nullptr) {
     ConfigureBoxLayoutView(this);
 
     auto* icon = AddChildView(std::make_unique<NonAccessibleImageView>());
     icon->SetImage(icon_model);
     icon->SetHorizontalAlignment(views::ImageView::Alignment::kLeading);
 
-    title_ = AddChildView(CreateLabelWithContextAndStyle(
+    views::StyledLabel* title = AddChildView(CreateLabelWithContextAndStyle(
         views::style::CONTEXT_DIALOG_TITLE, views::style::STYLE_PRIMARY));
-    subtitle_ = AddChildView(CreateLabelWithContextAndStyle(
+    title->SetText(l10n_util::GetStringUTF16(title_id));
+
+    views::StyledLabel* subtitle = AddChildView(CreateLabelWithContextAndStyle(
         views::style::CONTEXT_LABEL, views::style::STYLE_SECONDARY));
-  }
+    if (subtitle_link.has_value()) {
+      std::u16string link_text =
+          l10n_util::GetStringUTF16(subtitle_link->first);
+      size_t offset;
+      subtitle->SetText(
+          l10n_util::GetStringFUTF16(subtitle_id, link_text, &offset));
+      subtitle->AddStyleRange(gfx::Range(offset, offset + link_text.length()),
+                              views::StyledLabel::RangeStyleInfo::CreateForLink(
+                                  subtitle_link->second));
+    } else {
+      subtitle->SetText(l10n_util::GetStringUTF16(subtitle_id));
+    }
 
-  InstallerScreenView(const ui::ImageModel& icon_model,
-                      const std::u16string& title,
-                      const std::u16string& subtitle)
-      : InstallerScreenView(icon_model) {
-    SetTitle(title);
-    SetSubtitle(subtitle);
-  }
-
-  virtual void SetProgress(double percent, int minutes_remaining) {}
-
- protected:
-  void SetTitle(const std::u16string& title) { title_->SetText(title); }
-
-  void SetSubtitle(const std::u16string& subtitle) {
-    subtitle_->SetText(subtitle);
-  }
-
-  void SetSubtitleWithLink(const std::u16string& subtitle,
-                           const gfx::Range& link_range,
-                           base::RepeatingClosure link_handler) {
-    SetSubtitle(subtitle);
-    subtitle_->AddStyleRange(
-        link_range,
-        views::StyledLabel::RangeStyleInfo::CreateForLink(link_handler));
-  }
-
-  void SetContentsView(std::unique_ptr<views::View> contents) {
-    CHECK(!contents_);
-    contents_ = AddChildView(std::move(contents));
-    SetFlexForView(contents_, 1);
-  }
-
- private:
-  raw_ptr<views::StyledLabel> title_;
-  raw_ptr<views::StyledLabel> subtitle_;
-  raw_ptr<views::View> contents_;
-};
-BEGIN_METADATA(InstallerScreenView, views::BoxLayoutView)
-END_METADATA
-
-class GetMetadataScreen : public InstallerScreenView {
- public:
-  METADATA_HEADER(GetMetadataScreen);
-
-  GetMetadataScreen()
-      : InstallerScreenView(
-            ui::ImageModel::FromVectorIcon(kFingerprintIcon,
-                                           ui::kColorAccent,
-                                           kIconSize),
-            l10n_util::GetStringUTF16(IDS_IWA_INSTALLER_VERIFICATION_TITLE),
-            l10n_util::GetStringUTF16(
-                IDS_IWA_INSTALLER_VERIFICATION_SUBTITLE)) {
-    SetContentsView(CreateContentsView());
-  }
-
-  void SetProgress(double percent, int minutes_remaining) override {
-    progress_bar_->SetValue(percent / 100.0);
-  }
-
- private:
-  std::unique_ptr<views::View> CreateContentsView() {
-    auto progress_view = std::make_unique<views::BoxLayoutView>();
-    ConfigureBoxLayoutView(progress_view.get());
-    progress_view->SetInsideBorderInsets(
-        gfx::Insets::VH(0, kProgressViewHorizontalPadding));
-
-    progress_bar_ =
-        progress_view->AddChildView(std::make_unique<views::ProgressBar>());
-    progress_view->AddChildView(CreateLabelWithContextAndStyle(
-        views::style::CONTEXT_LABEL, views::style::STYLE_SECONDARY,
-        l10n_util::GetPluralStringFUTF16(IDS_IWA_INSTALLER_VERIFICATION_STATUS,
-                                         0)));
-    return progress_view;
-  }
-
-  raw_ptr<views::ProgressBar> progress_bar_;
-};
-BEGIN_METADATA(GetMetadataScreen, InstallerScreenView)
-END_METADATA
-
-class DisabledScreen : public InstallerScreenView {
- public:
-  METADATA_HEADER(DisabledScreen);
-
-  explicit DisabledScreen(base::RepeatingClosure change_preference_handler)
-      : InstallerScreenView(
-            ui::ImageModel::FromVectorIcon(vector_icons::kErrorOutlineIcon,
-                                           ui::kColorAlertMediumSeverityIcon,
-                                           kIconSize)) {
-    SetTitle(l10n_util::GetStringUTF16(IDS_IWA_INSTALLER_DISABLED_TITLE));
-
-    std::u16string change_preference =
-        l10n_util::GetStringUTF16(IDS_IWA_INSTALLER_DISABLED_CHANGE_PREFERENCE);
-    size_t offset;
-    std::u16string subtitle = l10n_util::GetStringFUTF16(
-        IDS_IWA_INSTALLER_DISABLED_SUBTITLE, change_preference, &offset);
-    SetSubtitleWithLink(subtitle,
-                        gfx::Range(offset, offset + change_preference.length()),
-                        change_preference_handler);
+    if (contents_view) {
+      views::View* contents = AddChildView(std::move(contents_view));
+      SetFlexForView(contents, 1);
+    }
   }
 };
-BEGIN_METADATA(DisabledScreen, InstallerScreenView)
+BEGIN_METADATA(InstallerDialogView, views::BoxLayoutView)
 END_METADATA
 
+// static
+void IsolatedWebAppInstallerView::SetDialogButtons(
+    views::DialogDelegate* dialog_delegate,
+    int close_button_label_id,
+    absl::optional<int> accept_button_label_id) {
+  if (!dialog_delegate) {
+    return;
+  }
+
+  int buttons = ui::DIALOG_BUTTON_CANCEL;
+  dialog_delegate->SetButtonLabel(
+      ui::DIALOG_BUTTON_CANCEL,
+      l10n_util::GetStringUTF16(close_button_label_id));
+  if (accept_button_label_id.has_value()) {
+    buttons |= ui::DIALOG_BUTTON_OK;
+    dialog_delegate->SetButtonLabel(
+        ui::DIALOG_BUTTON_OK,
+        l10n_util::GetStringUTF16(accept_button_label_id.value()));
+  }
+  dialog_delegate->SetButtons(buttons);
+}
+
 IsolatedWebAppInstallerView::IsolatedWebAppInstallerView(Delegate* delegate)
-    : delegate_(delegate), screen_(nullptr), initialized_(false) {}
+    : delegate_(delegate), dialog_view_(nullptr), initialized_(false) {}
 
 IsolatedWebAppInstallerView::~IsolatedWebAppInstallerView() = default;
 
 void IsolatedWebAppInstallerView::ShowDisabledScreen() {
-  ShowScreen(std::make_unique<DisabledScreen>(base::BindRepeating(
-      &Delegate::OnSettingsLinkClicked, base::Unretained(delegate_))));
+  InstallerDialogView::LinkInfo link(
+      IDS_IWA_INSTALLER_DISABLED_CHANGE_PREFERENCE,
+      base::BindRepeating(&Delegate::OnSettingsLinkClicked,
+                          base::Unretained(delegate_)));
+  ShowScreen(std::make_unique<InstallerDialogView>(
+      CreateImageModelFromVector(vector_icons::kErrorOutlineIcon,
+                                 ui::kColorAlertMediumSeverityIcon),
+      IDS_IWA_INSTALLER_DISABLED_TITLE, IDS_IWA_INSTALLER_DISABLED_SUBTITLE,
+      link));
 }
 
 void IsolatedWebAppInstallerView::ShowGetMetadataScreen() {
-  ShowScreen(std::make_unique<GetMetadataScreen>());
+  auto progress_view = std::make_unique<views::BoxLayoutView>();
+  ConfigureBoxLayoutView(progress_view.get());
+  progress_view->SetInsideBorderInsets(
+      gfx::Insets::VH(0, kProgressViewHorizontalPadding));
+
+  views::ProgressBar* progress_bar =
+      progress_view->AddChildView(std::make_unique<views::ProgressBar>());
+  progress_view->AddChildView(CreateLabelWithContextAndStyle(
+      views::style::CONTEXT_LABEL, views::style::STYLE_SECONDARY,
+      l10n_util::GetPluralStringFUTF16(IDS_IWA_INSTALLER_VERIFICATION_STATUS,
+                                       0)));
+
+  ShowScreen(std::make_unique<InstallerDialogView>(
+                 CreateImageModelFromVector(kFingerprintIcon, ui::kColorAccent),
+                 IDS_IWA_INSTALLER_VERIFICATION_TITLE,
+                 IDS_IWA_INSTALLER_VERIFICATION_SUBTITLE,
+                 /*subtitle_link=*/absl::nullopt, std::move(progress_view)),
+             progress_bar);
 }
 
 void IsolatedWebAppInstallerView::UpdateGetMetadataProgress(
     double percent,
     int minutes_remaining) {
-  CHECK(screen_);
-  screen_->SetProgress(percent, minutes_remaining);
+  CHECK(progress_bar_);
+  progress_bar_->SetValue(percent / 100.0);
 }
 
 void IsolatedWebAppInstallerView::ShowMetadataScreen(
     const SignedWebBundleMetadata& bundle_metadata) {
   // TODO(crbug.com/1479140): Implement
+  ShowDisabledScreen();
 }
 
 void IsolatedWebAppInstallerView::ShowInstallScreen(
@@ -224,18 +207,47 @@
 }
 
 void IsolatedWebAppInstallerView::ShowScreen(
-    std::unique_ptr<InstallerScreenView> screen) {
+    std::unique_ptr<InstallerDialogView> dialog_view,
+    views::ProgressBar* progress_bar) {
   if (!initialized_) {
     initialized_ = true;
     views::LayoutProvider* provider = views::LayoutProvider::Get();
     SetInsideBorderInsets(
         provider->GetInsetsMetric(views::InsetsMetric::INSETS_DIALOG));
   }
-
-  if (screen_) {
-    RemoveChildView(screen_);
+  progress_bar_ = progress_bar;
+  if (dialog_view_) {
+    RemoveChildView(dialog_view_);
   }
-  screen_ = AddChildView(std::move(screen));
+  dialog_view_ = AddChildView(std::move(dialog_view));
+  InvalidateLayout();
+}
+
+void IsolatedWebAppInstallerView::ShowDialog(
+    const IsolatedWebAppInstallerModel::DialogContent& dialog_content) {
+  CHECK(initialized_);
+  auto bubble_delegate = std::make_unique<views::BubbleDialogDelegate>(
+      GetWidget()->GetContentsView(), views::BubbleBorder::FLOAT);
+  bubble_delegate->SetModalType(ui::MODAL_TYPE_CHILD);
+  bubble_delegate->set_close_on_deactivate(false);
+
+  bubble_delegate->SetContentsView(std::make_unique<InstallerDialogView>(
+      dialog_content.is_error
+          ? CreateImageModelFromVector(vector_icons::kErrorOutlineIcon,
+                                       ui::kColorAlertMediumSeverityIcon)
+          : CreateImageModelFromVector(kSecurityIcon, ui::kColorAccent),
+      dialog_content.message, dialog_content.details,
+      dialog_content.details_link));
+
+  SetDialogButtons(bubble_delegate.get(), IDS_APP_CLOSE,
+                   /*accept_button_label_id=*/absl::nullopt);
+
+  bubble_delegate->SetCancelCallback(base::BindOnce(
+      &Delegate::OnChildDialogCanceled, base::Unretained(delegate_)));
+  bubble_delegate->SetAcceptCallback(base::BindOnce(
+      &Delegate::OnChildDialogAccepted, base::Unretained(delegate_)));
+
+  views::BubbleDialogDelegate::CreateBubble(std::move(bubble_delegate))->Show();
 }
 
 BEGIN_METADATA(IsolatedWebAppInstallerView, views::BoxLayoutView)
diff --git a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view.h b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view.h
index ff688eb..a1ade47 100644
--- a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view.h
+++ b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view.h
@@ -5,14 +5,23 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_WEB_APPS_ISOLATED_WEB_APPS_ISOLATED_WEB_APP_INSTALLER_VIEW_H_
 #define CHROME_BROWSER_UI_VIEWS_WEB_APPS_ISOLATED_WEB_APPS_ISOLATED_WEB_APP_INSTALLER_VIEW_H_
 
+#include <memory>
+
 #include "base/memory/raw_ptr.h"
+#include "chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_model.h"
 #include "chrome/browser/web_applications/isolated_web_apps/signed_web_bundle_metadata.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/layout/box_layout_view.h"
 
+namespace views {
+class DialogDelegate;
+class ProgressBar;
+}  // namespace views
+
 namespace web_app {
 
-class InstallerScreenView;
+class InstallerDialogView;
 class SignedWebBundleMetadata;
 
 // Responsible for displaying the contents section of the installation dialog:
@@ -32,9 +41,16 @@
  public:
   METADATA_HEADER(IsolatedWebAppInstallerView);
 
+  // Configures the buttons of the given DialogDelegate.
+  static void SetDialogButtons(views::DialogDelegate* dialog_delegate,
+                               int close_button_label_id,
+                               absl::optional<int> accept_button_label_id);
+
   class Delegate {
    public:
     virtual void OnSettingsLinkClicked() = 0;
+    virtual void OnChildDialogCanceled() = 0;
+    virtual void OnChildDialogAccepted() = 0;
   };
 
   explicit IsolatedWebAppInstallerView(Delegate* delegate);
@@ -55,11 +71,16 @@
   virtual void ShowInstallSuccessScreen(
       const SignedWebBundleMetadata& bundle_metadata);
 
+  virtual void ShowDialog(
+      const IsolatedWebAppInstallerModel::DialogContent& dialog_content);
+
  private:
-  void ShowScreen(std::unique_ptr<InstallerScreenView> screen);
+  void ShowScreen(std::unique_ptr<InstallerDialogView> screen,
+                  views::ProgressBar* progress_bar = nullptr);
 
   raw_ptr<Delegate> delegate_;
-  raw_ptr<InstallerScreenView> screen_;
+  raw_ptr<InstallerDialogView> dialog_view_;
+  raw_ptr<views::ProgressBar> progress_bar_;
   bool initialized_;
 };
 
diff --git a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.cc b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.cc
index b106f2f..2332a95f 100644
--- a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.cc
+++ b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/functional/callback.h"
-#include "base/logging.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_model.h"
@@ -23,6 +22,19 @@
 #include "ui/views/view.h"
 #include "ui/views/window/dialog_delegate.h"
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/webui/settings/public/constants/routes.mojom.h"
+#include "chrome/browser/ui/settings_window_manager_chromeos.h"
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "ash/webui/settings/public/constants/routes.mojom.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chromeos/crosapi/mojom/url_handler.mojom.h"
+#include "chromeos/lacros/lacros_service.h"
+#include "url/gurl.h"
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
 namespace web_app {
 
 namespace {
@@ -100,7 +112,10 @@
 void IsolatedWebAppInstallerViewController::OnBundleInvalid(
     const std::string& error) {
   // TODO(crbug.com/1479140): Show "failed to verify" error message
-  Close();
+  model_->SetDialogContent(IsolatedWebAppInstallerModel::DialogContent(
+      /*is_error=*/true, IDS_IWA_INSTALLER_VERIFICATION_ERROR_TITLE,
+      IDS_IWA_INSTALLER_VERIFICATION_ERROR_SUBTITLE));
+  OnModelChanged();
 }
 
 void IsolatedWebAppInstallerViewController::OnBundleInstallable(
@@ -125,6 +140,30 @@
 }
 
 void IsolatedWebAppInstallerViewController::OnSettingsLinkClicked() {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
+      profile_, chromeos::settings::mojom::kManageIsolatedWebAppsSubpagePath);
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  chromeos::LacrosService* service = chromeos::LacrosService::Get();
+  DCHECK(service->IsAvailable<crosapi::mojom::UrlHandler>());
+
+  GURL manage_isolated_web_apps_subpage_url =
+      GURL(chrome::kChromeUIOSSettingsURL)
+          .Resolve(
+              chromeos::settings::mojom::kManageIsolatedWebAppsSubpagePath);
+  service->GetRemote<crosapi::mojom::UrlHandler>()->OpenUrl(
+      manage_isolated_web_apps_subpage_url);
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+}
+
+void IsolatedWebAppInstallerViewController::OnChildDialogCanceled() {
+  // Currently all child dialogs should close the installer when closed.
+  Close();
+}
+
+void IsolatedWebAppInstallerViewController::OnChildDialogAccepted() {
   // TODO(crbug.com/1479140): Implement
 }
 
@@ -163,15 +202,23 @@
 }
 
 void IsolatedWebAppInstallerViewController::OnModelChanged() {
+  if (!view_) {
+    return;
+  }
+
   // TODO(crbug.com/1479140): Configure Install/Cancel buttons for all screens
   switch (model_->step()) {
     case IsolatedWebAppInstallerModel::Step::kDisabled:
-      SetButtons(IDS_APP_CLOSE, /*accept_button_label_id=*/absl::nullopt);
+      IsolatedWebAppInstallerView::SetDialogButtons(
+          dialog_delegate_, IDS_APP_CLOSE,
+          /*accept_button_label_id=*/absl::nullopt);
       view_->ShowDisabledScreen();
       break;
 
     case IsolatedWebAppInstallerModel::Step::kGetMetadata:
-      SetButtons(IDS_APP_CANCEL, /*accept_button_label_id=*/absl::nullopt);
+      IsolatedWebAppInstallerView::SetDialogButtons(
+          dialog_delegate_, IDS_APP_CANCEL,
+          /*accept_button_label_id=*/absl::nullopt);
       view_->ShowGetMetadataScreen();
       break;
 
@@ -187,26 +234,10 @@
       view_->ShowInstallSuccessScreen(model_->bundle_metadata());
       break;
   }
-}
 
-void IsolatedWebAppInstallerViewController::SetButtons(
-    int close_button_label_id,
-    absl::optional<int> accept_button_label_id) {
-  if (!dialog_delegate_) {
-    return;
+  if (model_->has_dialog_content()) {
+    view_->ShowDialog(model_->dialog_content());
   }
-
-  int buttons = ui::DIALOG_BUTTON_CANCEL;
-  dialog_delegate_->SetButtonLabel(
-      ui::DIALOG_BUTTON_CANCEL,
-      l10n_util::GetStringUTF16(close_button_label_id));
-  if (accept_button_label_id.has_value()) {
-    buttons |= ui::DIALOG_BUTTON_OK;
-    dialog_delegate_->SetButtonLabel(
-        ui::DIALOG_BUTTON_OK,
-        l10n_util::GetStringUTF16(accept_button_label_id.value()));
-  }
-  dialog_delegate_->SetButtons(buttons);
 }
 
 std::unique_ptr<views::DialogDelegate>
diff --git a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.h b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.h
index 15505b8..7de19d1 100644
--- a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.h
+++ b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.h
@@ -12,7 +12,6 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/views/web_apps/isolated_web_apps/installability_checker.h"
 #include "chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
 
@@ -66,13 +65,12 @@
 
   // `IsolatedWebAppInstallerView::Delegate`:
   void OnSettingsLinkClicked() override;
+  void OnChildDialogCanceled() override;
+  void OnChildDialogAccepted() override;
 
   // Updates the View to reflect the current state of the model.
   void OnModelChanged();
 
-  void SetButtons(int close_button_label_id,
-                  absl::optional<int> accept_button_label_id);
-
   std::unique_ptr<views::DialogDelegate> CreateDialogDelegate(
       std::unique_ptr<views::View> contents_view);
 
diff --git a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller_unittest.cc b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller_unittest.cc
index 02b9d21..7761ab6 100644
--- a/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller_unittest.cc
+++ b/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller_unittest.cc
@@ -27,7 +27,9 @@
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/url_constants.h"
+#include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_task_environment.h"
 #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
@@ -39,11 +41,33 @@
 namespace web_app {
 namespace {
 
-using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Exactly;
+using ::testing::ExplainMatchResult;
+using ::testing::Field;
 using ::testing::Invoke;
+using ::testing::Property;
+using DialogContent = IsolatedWebAppInstallerModel::DialogContent;
 
 constexpr base::StringPiece kIconPath = "/icon.png";
 
+MATCHER_P3(WithMetadata, app_id, app_name, version, "") {
+  return ExplainMatchResult(
+      AllOf(Property("app_id", &SignedWebBundleMetadata::app_id, app_id),
+            Property("app_name", &SignedWebBundleMetadata::app_name, app_name),
+            Property("version", &SignedWebBundleMetadata::version,
+                     base::Version(version))),
+      arg, result_listener);
+}
+
+MATCHER_P3(WithContents, is_error, message_id, details_id, "") {
+  return ExplainMatchResult(
+      AllOf(Field("is_error", &DialogContent::is_error, is_error),
+            Field("message_id", &DialogContent::message, message_id),
+            Field("details_id", &DialogContent::details, details_id)),
+      arg, result_listener);
+}
+
 IsolatedWebAppUrlInfo CreateAndWriteTestBundle(
     const base::FilePath& bundle_path,
     const std::string& version) {
@@ -103,9 +127,16 @@
               ShowInstallSuccessScreen,
               (const SignedWebBundleMetadata& bundle_metadata),
               (override));
+  MOCK_METHOD(
+      void,
+      ShowDialog,
+      (const IsolatedWebAppInstallerModel::DialogContent& dialog_content),
+      (override));
 
   // `IsolatedWebAppInstallerView::Delegate`:
   MOCK_METHOD(void, OnSettingsLinkClicked, (), (override));
+  MOCK_METHOD(void, OnChildDialogCanceled, (), (override));
+  MOCK_METHOD(void, OnChildDialogAccepted, (), (override));
 };
 
 class IsolatedWebAppInstallerViewControllerTest : public ::testing::Test {
@@ -177,16 +208,46 @@
   testing::StrictMock<MockView> view;
   controller.SetViewForTesting(&view);
 
-  base::test::TestFuture<SignedWebBundleMetadata> bundle_metadata;
+  base::test::TestFuture<void> callback;
   EXPECT_CALL(view, ShowGetMetadataScreen());
-  EXPECT_CALL(view, ShowMetadataScreen(_))
-      .WillOnce(
-          Invoke(&bundle_metadata,
-                 &base::test::TestFuture<SignedWebBundleMetadata>::SetValue));
+  EXPECT_CALL(
+      view, ShowMetadataScreen(WithMetadata("hoealecpbefphiclhampllbdbdpfmfpi",
+                                            u"test app name", "7.7.7")))
+      .WillOnce(Invoke(&callback, &base::test::TestFuture<void>::SetValue));
 
   controller.Start();
 
-  EXPECT_TRUE(bundle_metadata.Wait());
+  EXPECT_TRUE(callback.Wait());
+}
+
+TEST_F(IsolatedWebAppInstallerViewControllerTest,
+       InvalidBundleShowsErrorDialog) {
+  base::FilePath bundle_path = CreateBundlePath("test_bundle.swbn");
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    CHECK(base::WriteFile(bundle_path, "not a valid bundle"));
+  }
+  auto url_info = IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(
+      web_package::SignedWebBundleId::CreateRandomForDevelopment());
+  MockIconAndPageState(url_info);
+
+  IsolatedWebAppInstallerModel model(bundle_path);
+  IsolatedWebAppInstallerViewController controller(profile(), fake_provider(),
+                                                   &model);
+  testing::StrictMock<MockView> view;
+  controller.SetViewForTesting(&view);
+
+  base::test::TestFuture<void> callback;
+  EXPECT_CALL(view, ShowGetMetadataScreen()).Times(Exactly(2));
+  EXPECT_CALL(view,
+              ShowDialog(WithContents(
+                  /*is_error=*/true, IDS_IWA_INSTALLER_VERIFICATION_ERROR_TITLE,
+                  IDS_IWA_INSTALLER_VERIFICATION_ERROR_SUBTITLE)))
+      .WillOnce(Invoke(&callback, &base::test::TestFuture<void>::SetValue));
+
+  controller.Start();
+
+  EXPECT_TRUE(callback.Wait());
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc b/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
index b465eef..cf487db 100644
--- a/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
@@ -5,11 +5,14 @@
 #include <tuple>
 
 #include "base/location.h"
+#include "base/metrics/field_trial_params.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/bind.h"
+#include "base/test/gmock_expected_support.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_future.h"
+#include "base/types/expected.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/apps/app_service/app_registry_cache_waiter.h"
@@ -17,7 +20,6 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/intent_helper/preferred_apps_test_util.h"
 #include "chrome/browser/apps/link_capturing/link_capturing_feature_test_support.h"
-#include "chrome/browser/apps/link_capturing/link_capturing_features.h"
 #include "chrome/browser/apps/link_capturing/link_capturing_navigation_throttle.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -32,20 +34,18 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/test/web_app_test_observers.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/hit_test_region_observer.h"
 #include "content/public/test/prerender_test_util.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
-#include "content/public/test/url_loader_interceptor.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom.h"
 
@@ -62,13 +62,16 @@
 
 // Tests that links are captured correctly into an installed WebApp using the
 // 'tabbed' display mode, which allows the webapp window to have multiple tabs.
-class WebAppLinkCapturingBrowserTest : public WebAppNavigationBrowserTest {
+class WebAppLinkCapturingBrowserTest
+    : public WebAppNavigationBrowserTest,
+      public testing::WithParamInterface<bool> {
  public:
   WebAppLinkCapturingBrowserTest() {
     std::vector<base::test::FeatureRefAndParams> features_and_params = {
         {blink::features::kWebAppEnableLaunchHandler, {}}};
 #if !BUILDFLAG(IS_CHROMEOS)
-    auto features_to_enable = apps::test::GetFeaturesToEnableLinkCapturingUX();
+    auto features_to_enable = apps::test::GetFeaturesToEnableLinkCapturingUX(
+        /*override_captures_by_default=*/GetParam());
     std::move(std::begin(features_to_enable), std::end(features_to_enable),
               std::back_inserter(features_and_params));
 #endif
@@ -79,6 +82,8 @@
   }
   ~WebAppLinkCapturingBrowserTest() override = default;
 
+  bool LinkCapturingEnabledByDefault() const { return GetParam(); }
+
   void SetUpOnMainThread() override {
     WebAppNavigationBrowserTest::SetUpOnMainThread();
     ASSERT_TRUE(https_server().Start());
@@ -109,6 +114,10 @@
     return embedded_test_server()->GetURL("/web_apps/nesting/index.html");
   }
 
+  // Note: This must be installed AFTER installing the nested app, as the
+  // `InstallWebAppFromPageAndCloseAppBrowser` function does a link-like
+  // navigation to open the url, which would be captured by the parent app if
+  // installed first.
   webapps::AppId InstallParentApp() {
     GURL start_url = GetParentAppUrl();
     webapps::AppId app_id =
@@ -117,6 +126,10 @@
     return app_id;
   }
 
+  // Note: This must be installed BEFORE installing the parent app, as the
+  // `InstallWebAppFromPageAndCloseAppBrowser` function does a link-like
+  // navigation to open the url, which would be captured by the parent app if
+  // installed first.
   webapps::AppId InstallNestedApp() {
     GURL start_url = GetNestedAppUrl();
     webapps::AppId app_id =
@@ -200,17 +213,6 @@
     }
   }
 
-  void TurnOnLinkCapturing(webapps::AppId app_id) {
-#if BUILDFLAG(IS_CHROMEOS)
-    apps_util::SetSupportedLinksPreferenceAndWait(profile(), app_id);
-#else
-    base::test::TestFuture<void> preference_set;
-    provider().scheduler().SetAppCapturesSupportedLinksDisableOverlapping(
-        app_id, true, preference_set.GetCallback());
-    ASSERT_TRUE(preference_set.Wait());
-#endif  // BUILDFLAG(IS_CHROMEOS)
-  }
-
   absl::optional<LaunchHandler> GetLaunchHandler(const webapps::AppId& app_id) {
     return provider().registrar_unsafe().GetAppById(app_id)->launch_handler();
   }
@@ -226,7 +228,7 @@
 
 // Link capturing with navigate_existing_client: always should navigate existing
 // app windows.
-IN_PROC_BROWSER_TEST_F(WebAppLinkCapturingBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebAppLinkCapturingBrowserTest,
                        NavigateExistingClientFromBrowser) {
   const auto [app_id, in_scope_1, _, scope] = InstallTestApp(
       "/web_apps/get_manifest.html?"
@@ -234,7 +236,8 @@
   EXPECT_EQ(GetLaunchHandler(app_id),
             (LaunchHandler{ClientMode::kNavigateExisting}));
 
-  TurnOnLinkCapturing(app_id);
+  ASSERT_EQ(apps::test::EnableLinkCapturingByUser(profile(), app_id),
+            base::ok());
 
   // Start browser at an out of scope page.
   Navigate(browser(), out_of_scope_);
@@ -258,11 +261,12 @@
 }
 
 // Link captures from about:blank cleans up the about:blank page.
-IN_PROC_BROWSER_TEST_F(WebAppLinkCapturingBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebAppLinkCapturingBrowserTest,
                        AboutBlankNavigationCleanUp) {
   const auto [app_id, in_scope_1, _, scope] =
       InstallTestApp("/web_apps/basic.html");
-  TurnOnLinkCapturing(app_id);
+  ASSERT_EQ(apps::test::EnableLinkCapturingByUser(profile(), app_id),
+            base::ok());
 
   ExpectTabs(browser(), {about_blank_});
   BrowserChangeObserver removed_observer(
@@ -288,11 +292,12 @@
 #define MAYBE_JavascriptAboutBlankNavigationCleanUp \
   JavascriptAboutBlankNavigationCleanUp
 #endif
-IN_PROC_BROWSER_TEST_F(WebAppLinkCapturingBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebAppLinkCapturingBrowserTest,
                        MAYBE_JavascriptAboutBlankNavigationCleanUp) {
   const auto [app_id, in_scope_1, _, scope] =
       InstallTestApp("/web_apps/basic.html");
-  TurnOnLinkCapturing(app_id);
+  ASSERT_EQ(apps::test::EnableLinkCapturingByUser(profile(), app_id),
+            base::ok());
 
   ExpectTabs(browser(), {about_blank_});
   BrowserChangeObserver removed_observer(
@@ -318,7 +323,7 @@
   ASSERT_TRUE(future.Wait());
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppLinkCapturingBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebAppLinkCapturingBrowserTest,
                        DifferentPortConsideredDifferent) {
   net::EmbeddedTestServer other_server;
   other_server.AddDefaultHandlers(GetChromeTestDataDir());
@@ -332,7 +337,8 @@
 
   const auto [app_id, url1, url2, scope] =
       InstallTestApp("/web_apps/basic.html");
-  TurnOnLinkCapturing(app_id);
+  ASSERT_EQ(apps::test::EnableLinkCapturingByUser(profile(), app_id),
+            base::ok());
 
   ExpectTabs(browser(), {about_blank_});
   GURL url = other_server.GetURL("/web_apps/basic.html");
@@ -341,11 +347,12 @@
 }
 
 // Tests that links to apps from sandboxed iframes can be captured.
-IN_PROC_BROWSER_TEST_F(WebAppLinkCapturingBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebAppLinkCapturingBrowserTest,
                        HandleClickFromSandboxedIframe) {
   const auto [app_id, in_scope_1, _, scope] =
       InstallTestApp("/web_apps/basic.html");
-  TurnOnLinkCapturing(app_id);
+  ASSERT_EQ(apps::test::EnableLinkCapturingByUser(profile(), app_id),
+            base::ok());
 
   // Create a sandboxed iframe, which contains a link to the installed app,
   // covering the full viewport of the iframe.
@@ -380,12 +387,17 @@
   EXPECT_TRUE(AppBrowserController::IsForWebApp(app_browser, app_id));
 }
 
-IN_PROC_BROWSER_TEST_F(WebAppLinkCapturingBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebAppLinkCapturingBrowserTest,
                        ParentAppWithChildLinks) {
-  webapps::AppId parent_app_id = InstallParentApp();
+  // Note: The order matters so the nested app navigation for installation
+  // doesn't get captured by the parent app.
   webapps::AppId nested_app_id = InstallNestedApp();
+  webapps::AppId parent_app_id = InstallParentApp();
 
-  TurnOnLinkCapturing(parent_app_id);
+  if (!LinkCapturingEnabledByDefault()) {
+    ASSERT_EQ(apps::test::EnableLinkCapturingByUser(profile(), parent_app_id),
+              base::ok());
+  }
   AddTab(browser(), about_blank_);
 
   BrowserChangeObserver added_observer(
@@ -403,7 +415,17 @@
   ExpectTabs(app_browser, {GetNestedAppUrl()});
   ExpectTabs(browser(), {about_blank_});
 #else
-  ExpectTabs(browser(), {about_blank_, GetNestedAppUrl()});
+  if (LinkCapturingEnabledByDefault()) {
+    // If link capturing is on by default, then the nested app will also be
+    // capturing links in it's scope (and thus the nested url will launch a
+    // nested app browser. the nested app browser.
+    Browser* app_browser = added_observer.Wait();
+    EXPECT_TRUE(AppBrowserController::IsForWebApp(app_browser, nested_app_id));
+    EXPECT_NE(browser(), app_browser);
+    ExpectTabs(app_browser, {GetNestedAppUrl()});
+  } else {
+    ExpectTabs(browser(), {about_blank_, GetNestedAppUrl()});
+  }
 #endif
 }
 
@@ -412,13 +434,19 @@
 // URL space and fully respect the child app's user setting.
 // Thus, on non-CrOS platforms both apps can capture links.
 #if !BUILDFLAG(IS_CHROMEOS)
-IN_PROC_BROWSER_TEST_F(WebAppLinkCapturingBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebAppLinkCapturingBrowserTest,
                        ParentAppAndChildAppCapture) {
-  webapps::AppId parent_app_id = InstallParentApp();
+  // Note: The order matters so the nested app navigation for installation
+  // doesn't get captured by the parent app.
   webapps::AppId nested_app_id = InstallNestedApp();
+  webapps::AppId parent_app_id = InstallParentApp();
 
-  TurnOnLinkCapturing(parent_app_id);
-  TurnOnLinkCapturing(nested_app_id);
+  if (!LinkCapturingEnabledByDefault()) {
+    ASSERT_EQ(apps::test::EnableLinkCapturingByUser(profile(), nested_app_id),
+              base::ok());
+    ASSERT_EQ(apps::test::EnableLinkCapturingByUser(profile(), parent_app_id),
+              base::ok());
+  }
 
   Browser* nested_browser;
   Browser* parent_browser;
@@ -455,12 +483,17 @@
 #endif  // !BUILDFLAG(IS_CHROMEOS)
 
 // Tests that link capturing works while inside a web app window.
-IN_PROC_BROWSER_TEST_F(WebAppLinkCapturingBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebAppLinkCapturingBrowserTest,
                        LinkCaptureInWebAppWindow) {
-  webapps::AppId parent_app_id = InstallParentApp();
+  // Note: The order matters so the nested app navigation for installation
+  // doesn't get captured by the parent app.
   webapps::AppId nested_app_id = InstallNestedApp();
+  webapps::AppId parent_app_id = InstallParentApp();
 
-  TurnOnLinkCapturing(nested_app_id);
+  if (!LinkCapturingEnabledByDefault()) {
+    ASSERT_EQ(apps::test::EnableLinkCapturingByUser(profile(), nested_app_id),
+              base::ok());
+  }
 
   content::WebContents* parent_app = OpenApplication(parent_app_id);
 
@@ -487,6 +520,13 @@
   // Links clicked within an app popup browser will also capture.
   {
     const gfx::Size size(500, 500);
+    // The parent link capturing must be turned off or the popup window url will
+    // automatically capture.
+    if (LinkCapturingEnabledByDefault()) {
+      ASSERT_EQ(
+          apps::test::DisableLinkCapturingByUser(profile(), parent_app_id),
+          base::ok());
+    }
     Browser* const popup_browser = OpenPopupAndWait(
         chrome::FindBrowserWithTab(parent_app), GetParentAppUrl(), size);
 
@@ -500,6 +540,18 @@
   }
 }
 
+INSTANTIATE_TEST_SUITE_P(,
+                         WebAppLinkCapturingBrowserTest,
+#if BUILDFLAG(IS_CHROMEOS)
+                         testing::Values(false),
+#else
+                         testing::Values(true, false),
+#endif
+                         [](const testing::TestParamInfo<bool>& info) {
+                           return info.param ? "CapturingDefaultOn"
+                                             : "CapturingDefaultOff";
+                         });
+
 // TODO: Run these tests on Chrome OS with both Ash and Lacros processes active.
 class WebAppTabStripLinkCapturingBrowserTest
     : public WebAppLinkCapturingBrowserTest {
@@ -528,10 +580,11 @@
 
 // First in scope navigation from out of scope gets captured and reparented into
 // the app window.
-IN_PROC_BROWSER_TEST_F(WebAppTabStripLinkCapturingBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebAppTabStripLinkCapturingBrowserTest,
                        InScopeNavigationsCaptured) {
   const auto [app_id, in_scope_1, in_scope_2, scope] = InstallTestTabbedApp();
-  TurnOnLinkCapturing(app_id);
+  ASSERT_EQ(apps::test::EnableLinkCapturingByUser(profile(), app_id),
+            base::ok());
 
   // Start browser at an out of scope page.
   Navigate(browser(), out_of_scope_);
@@ -566,5 +619,17 @@
   ExpectTabs(app_browser, {in_scope_1, in_scope_2, scope});
 }
 
+INSTANTIATE_TEST_SUITE_P(,
+                         WebAppTabStripLinkCapturingBrowserTest,
+#if BUILDFLAG(IS_CHROMEOS)
+                         testing::Values(false),
+#else
+                         testing::Values(true, false),
+#endif
+                         [](const testing::TestParamInfo<bool>& info) {
+                           return info.param ? "CapturingDefaultOn"
+                                             : "CapturingDefaultOff";
+                         });
+
 }  // namespace
 }  // namespace web_app
diff --git a/chrome/browser/ui/webid/identity_dialog_controller.cc b/chrome/browser/ui/webid/identity_dialog_controller.cc
index a40f166..1f3def22 100644
--- a/chrome/browser/ui/webid/identity_dialog_controller.cc
+++ b/chrome/browser/ui/webid/identity_dialog_controller.cc
@@ -31,8 +31,10 @@
     content::IdentityRequestAccount::SignInMode sign_in_mode,
     bool show_auto_reauthn_checkbox,
     AccountSelectionCallback on_selected,
+    SigninToIdPCallback on_add_account,
     DismissCallback dismiss_callback) {
   on_account_selection_ = std::move(on_selected);
+  on_signin_ = std::move(on_add_account);
   on_dismiss_ = std::move(dismiss_callback);
   if (!account_view_)
     account_view_ = AccountSelectionView::Create(this);
diff --git a/chrome/browser/ui/webid/identity_dialog_controller.h b/chrome/browser/ui/webid/identity_dialog_controller.h
index c9fe215..ca74c1f 100644
--- a/chrome/browser/ui/webid/identity_dialog_controller.h
+++ b/chrome/browser/ui/webid/identity_dialog_controller.h
@@ -46,6 +46,7 @@
       content::IdentityRequestAccount::SignInMode sign_in_mode,
       bool show_auto_reauthn_checkbox,
       AccountSelectionCallback on_selected,
+      SigninToIdPCallback on_add_account,
       DismissCallback dismiss_callback) override;
   void ShowFailureDialog(const std::string& top_frame_for_display,
                          const absl::optional<std::string>& iframe_for_display,
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc
index 915a8f7c..5a618bd 100644
--- a/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/apps/link_capturing/link_capturing_features.h"
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom-shared.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
+#include "chrome/browser/web_applications/test/web_app_test.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
@@ -61,12 +62,14 @@
   }
 };
 }  // namespace
-class AppManagementPageHandlerTestBase : public testing::Test {
+
+class AppManagementPageHandlerTestBase
+    : public WebAppTest,
+      public testing::WithParamInterface<bool> {
  public:
   void SetUp() override {
-    testing::Test::SetUp();
+    WebAppTest::SetUp();
 
-    profile_ = std::make_unique<TestingProfile>();
     delegate_ = std::unique_ptr<TestDelegate>();
 
     web_app::test::AwaitStartWebAppProviderAndSubsystems(profile());
@@ -75,16 +78,23 @@
     mojo::Remote<app_management::mojom::PageHandler> handler;
     handler_ = std::make_unique<AppManagementPageHandler>(
         handler.BindNewPipeAndPassReceiver(),
-        page.InitWithNewPipeAndPassRemote(), profile_.get(), *delegate_.get());
+        page.InitWithNewPipeAndPassRemote(), profile(), *delegate_.get());
 #if !BUILDFLAG(IS_CHROMEOS)
-    auto features_to_enable = apps::test::GetFeaturesToEnableLinkCapturingUX();
-    features_to_enable.push_back(
+    auto features_and_params = apps::test::GetFeaturesToEnableLinkCapturingUX(
+        /*override_captures_by_default=*/GetParam());
+    features_and_params.push_back(
         {blink::features::kWebAppEnableScopeExtensions, {}});
-    scoped_feature_list_.InitWithFeaturesAndParameters(features_to_enable, {});
+    scoped_feature_list_.InitWithFeaturesAndParameters(features_and_params, {});
 #endif  // !BUILDFLAG(IS_CHROMEOS)
   }
 
-  Profile* profile() { return profile_.get(); }
+  void TearDown() override {
+    handler_.reset();
+    WebAppTest::TearDown();
+  }
+
+  bool LinkCapturingEnabledByDefault() { return GetParam(); }
+
   AppManagementPageHandler* handler() { return handler_.get(); }
 
  protected:
@@ -109,9 +119,7 @@
   }
 
  private:
-  content::BrowserTaskEnvironment task_environment_;
   data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
-  std::unique_ptr<TestingProfile> profile_;
   std::unique_ptr<TestDelegate> delegate_;
   std::unique_ptr<AppManagementPageHandler> handler_;
 #if !BUILDFLAG(IS_CHROMEOS)
@@ -119,7 +127,7 @@
 #endif  // !BUILDFLAG(IS_CHROMEOS)
 };
 
-TEST_F(AppManagementPageHandlerTestBase, GetApp) {
+TEST_P(AppManagementPageHandlerTestBase, GetApp) {
   // Create a web app entry with scope, which would be recognised
   // as normal web app in the web app system.
   auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
@@ -137,7 +145,7 @@
   EXPECT_EQ(result.Get()->type, AppType::kWeb);
 }
 
-TEST_F(AppManagementPageHandlerTestBase, GetPreferredAppTest) {
+TEST_P(AppManagementPageHandlerTestBase, GetPreferredAppTest) {
   auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info->title = u"app_name";
   web_app_info->start_url = GURL("https://example.com/index.html");
@@ -146,6 +154,10 @@
   std::string app_id =
       web_app::test::InstallWebApp(profile(), std::move(web_app_info));
 
+  if (LinkCapturingEnabledByDefault()) {
+    EXPECT_TRUE(IsAppPreferred(app_id));
+    ASSERT_EQ(test::DisableLinkCapturingByUser(profile(), app_id), base::ok());
+  }
   EXPECT_FALSE(IsAppPreferred(app_id));
 
   handler()->SetPreferredApp(app_id, /*is_preferred_app=*/true);
@@ -159,8 +171,25 @@
               testing::Contains("example.com/abc/*"));
 }
 
+TEST_P(AppManagementPageHandlerTestBase, DisablePreferredApp) {
+  auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
+  web_app_info->title = u"app_name";
+  web_app_info->start_url = GURL("https://example.com/index.html");
+  web_app_info->scope = GURL("https://example.com/abc/");
+
+  std::string app_id =
+      web_app::test::InstallWebApp(profile(), std::move(web_app_info));
+
+  handler()->SetPreferredApp(app_id, /*is_preferred_app=*/false);
+  AwaitWebAppCommandsComplete();
+
+  base::test::TestFuture<app_management::mojom::AppPtr> updated_result;
+  handler()->GetApp(app_id, updated_result.GetCallback());
+  EXPECT_FALSE(updated_result.Get()->is_preferred_app);
+}
+
 #if !BUILDFLAG(IS_CHROMEOS)
-TEST_F(AppManagementPageHandlerTestBase, SupportedLinksWithPort) {
+TEST_P(AppManagementPageHandlerTestBase, SupportedLinksWithPort) {
   auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info->title = u"app_name";
   web_app_info->start_url = GURL("https://example.com/index.html");
@@ -175,7 +204,7 @@
               testing::Contains("example:8080/abc/*"));
 }
 
-TEST_F(AppManagementPageHandlerTestBase, PreferredAppNonOverlappingScopePort) {
+TEST_P(AppManagementPageHandlerTestBase, PreferredAppNonOverlappingScopePort) {
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info1->title = u"App 1";
   web_app_info1->start_url = GURL("https://example.com/index.html");
@@ -191,14 +220,14 @@
 
   std::string app_id2 =
       web_app::test::InstallWebApp(profile(), std::move(web_app_info2));
-  EXPECT_FALSE(IsAppPreferred(app_id1));
-  EXPECT_FALSE(IsAppPreferred(app_id2));
+  EXPECT_EQ(IsAppPreferred(app_id1), LinkCapturingEnabledByDefault());
+  EXPECT_EQ(IsAppPreferred(app_id2), LinkCapturingEnabledByDefault());
 
   // app_id1 is set to preferred, app_id2 is not affected.
   handler()->SetPreferredApp(app_id1, /*is_preferred_app=*/true);
   AwaitWebAppCommandsComplete();
   EXPECT_TRUE(IsAppPreferred(app_id1));
-  EXPECT_FALSE(IsAppPreferred(app_id2));
+  EXPECT_EQ(IsAppPreferred(app_id2), LinkCapturingEnabledByDefault());
 
   // app_id2 is set as preferred, app_id1 is not affected.
   handler()->SetPreferredApp(app_id2, /*is_preferred_app=*/true);
@@ -208,7 +237,7 @@
 }
 #endif  // !BUILDFLAG(IS_CHROMEOS)
 
-TEST_F(AppManagementPageHandlerTestBase, PreferredAppOverlappingScopePort) {
+TEST_P(AppManagementPageHandlerTestBase, PreferredAppOverlappingScopePort) {
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info1->title = u"App 1";
   web_app_info1->start_url = GURL("https://example.com/index.html");
@@ -224,14 +253,14 @@
 
   std::string app_id2 =
       web_app::test::InstallWebApp(profile(), std::move(web_app_info2));
-  EXPECT_FALSE(IsAppPreferred(app_id1));
-  EXPECT_FALSE(IsAppPreferred(app_id2));
+  EXPECT_EQ(IsAppPreferred(app_id1), LinkCapturingEnabledByDefault());
+  EXPECT_EQ(IsAppPreferred(app_id2), LinkCapturingEnabledByDefault());
 
   // Setting app_id1 as preferred should set app_id2 as not preferred.
   handler()->SetPreferredApp(app_id1, /*is_preferred_app=*/true);
   AwaitWebAppCommandsComplete();
   EXPECT_TRUE(IsAppPreferred(app_id1));
-  EXPECT_FALSE(IsAppPreferred(app_id2));
+  EXPECT_EQ(IsAppPreferred(app_id2), LinkCapturingEnabledByDefault());
 
   handler()->SetPreferredApp(app_id2, /*is_preferred_app=*/true);
   AwaitWebAppCommandsComplete();
@@ -249,7 +278,7 @@
   EXPECT_TRUE(IsAppPreferred(app_id2));
 }
 
-TEST_F(AppManagementPageHandlerTestBase,
+TEST_P(AppManagementPageHandlerTestBase,
        GetPreferredAppDifferentScopesNotReset) {
   // Install app1 and mark it as preferred.
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
@@ -295,7 +324,7 @@
   EXPECT_TRUE(IsAppPreferred(app_id3));
 }
 
-TEST_F(AppManagementPageHandlerTestBase, GetPreferredAppTestInvalidAppId) {
+TEST_P(AppManagementPageHandlerTestBase, GetPreferredAppTestInvalidAppId) {
   auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info->title = u"app_name";
   web_app_info->start_url = GURL("https://example.com/index.html");
@@ -304,12 +333,17 @@
   std::string app_id =
       web_app::test::InstallWebApp(profile(), std::move(web_app_info));
 
+  if (LinkCapturingEnabledByDefault()) {
+    EXPECT_TRUE(IsAppPreferred(app_id));
+    ASSERT_EQ(test::DisableLinkCapturingByUser(profile(), app_id), base::ok());
+  }
+
   EXPECT_FALSE(IsAppPreferred(app_id));
   handler()->SetPreferredApp("def", /*is_preferred_app=*/true);
   EXPECT_FALSE(IsAppPreferred(app_id));
 }
 
-TEST_F(AppManagementPageHandlerTestBase,
+TEST_P(AppManagementPageHandlerTestBase,
        GetPreferredAppTestInvalidSupportedLink) {
   auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info->title = u"app_name";
@@ -319,6 +353,11 @@
   std::string app_id =
       web_app::test::InstallWebApp(profile(), std::move(web_app_info));
 
+  if (LinkCapturingEnabledByDefault()) {
+    EXPECT_TRUE(IsAppPreferred(app_id));
+    ASSERT_EQ(test::DisableLinkCapturingByUser(profile(), app_id), base::ok());
+  }
+
   EXPECT_FALSE(IsAppPreferred(app_id));
 
   handler()->SetPreferredApp(app_id, /*is_preferred_app=*/true);
@@ -329,7 +368,7 @@
   EXPECT_TRUE(updated_result.Get()->supported_links.empty());
 }
 
-TEST_F(AppManagementPageHandlerTestBase,
+TEST_P(AppManagementPageHandlerTestBase,
        GetOverlappingPreferredAppsSingleAppOnly) {
   // First install an app that has some scope set in it.
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
@@ -351,6 +390,11 @@
   std::string app_id2 =
       web_app::test::InstallWebApp(profile(), std::move(web_app_info2));
 
+  if (LinkCapturingEnabledByDefault()) {
+    EXPECT_TRUE(IsAppPreferred(app_id1));
+    ASSERT_EQ(test::DisableLinkCapturingByUser(profile(), app_id1), base::ok());
+  }
+
   // Set app_id1 as a preferred app.
   handler()->SetPreferredApp(app_id1, /*is_preferred_app=*/true);
   AwaitWebAppCommandsComplete();
@@ -360,7 +404,7 @@
   EXPECT_TRUE(overlapping_apps.empty());
 }
 
-TEST_F(AppManagementPageHandlerTestBase,
+TEST_P(AppManagementPageHandlerTestBase,
        GetOverlappingPreferredAppsNestedScope) {
   // First install an app that has some scope set in it.
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
@@ -399,7 +443,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
 }
 
-TEST_F(AppManagementPageHandlerTestBase, GetOverlappingPreferredAppsTwice) {
+TEST_P(AppManagementPageHandlerTestBase, GetOverlappingPreferredAppsTwice) {
   // First install an app that has some scope set in it.
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info1->title = u"app_name";
@@ -423,6 +467,7 @@
   // Set app_id1 as a preferred app.
   handler()->SetPreferredApp(app_id1, /*is_preferred_app=*/true);
   AwaitWebAppCommandsComplete();
+  EXPECT_FALSE(IsAppPreferred(app_id2));
 
   std::vector<std::string> overlapping_apps =
       GetOverlappingPreferredApps(app_id1);
@@ -437,7 +482,7 @@
   EXPECT_THAT(overlapping_apps, testing::ElementsAre(app_id2));
 }
 
-TEST_F(AppManagementPageHandlerTestBase,
+TEST_P(AppManagementPageHandlerTestBase,
        GetOverlappingPreferredAppsTwiceNonPreferred) {
   // First install an app that has some scope set in it.
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
@@ -462,6 +507,7 @@
   // Set app_id1 as a preferred app.
   handler()->SetPreferredApp(app_id1, /*is_preferred_app=*/true);
   AwaitWebAppCommandsComplete();
+  EXPECT_FALSE(IsAppPreferred(app_id2));
 
   std::vector<std::string> overlapping_apps =
       GetOverlappingPreferredApps(app_id1);
@@ -477,7 +523,7 @@
   EXPECT_TRUE(overlapping_apps.empty());
 }
 
-TEST_F(AppManagementPageHandlerTestBase,
+TEST_P(AppManagementPageHandlerTestBase,
        GetOverlappingPreferredAppsShortcutApp) {
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info1->title = u"app_name";
@@ -507,7 +553,7 @@
 // On ChromeOS, it's possible for the supported links preference file to contain
 // references to apps that don't exist. These should be filtered out from the
 // GetOverlappingPreferredApps call.
-TEST_F(AppManagementPageHandlerTestBase,
+TEST_P(AppManagementPageHandlerTestBase,
        GetOverlappingPreferredAppsInvalidApp) {
   auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info->title = u"app_name";
@@ -529,7 +575,7 @@
 }
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
-TEST_F(AppManagementPageHandlerTestBase, DifferentScopeNoOverlap) {
+TEST_P(AppManagementPageHandlerTestBase, DifferentScopeNoOverlap) {
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info1->title = u"app_name";
   web_app_info1->start_url = GURL("https://example.com/index.html");
@@ -555,7 +601,7 @@
 }
 
 #if !BUILDFLAG(IS_CHROMEOS)
-TEST_F(AppManagementPageHandlerTestBase, GetScopeExtensions) {
+TEST_P(AppManagementPageHandlerTestBase, GetScopeExtensions) {
   auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info->title = u"app_name";
   web_app_info->start_url = GURL("https://example.com/");
@@ -610,7 +656,7 @@
 // TODO(crbug.com/1476011): The overlapping nested scope based behavior is only
 // on ChromeOS, and will need to be modified if the behavior changes.
 #if BUILDFLAG(IS_CHROMEOS)
-TEST_F(AppManagementPageHandlerTestBase, UseCase_ADisabledBDisabled) {
+TEST_P(AppManagementPageHandlerTestBase, UseCase_ADisabledBDisabled) {
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info1->title = u"A";
   web_app_info1->start_url = GURL("https://example.com/index.html");
@@ -638,7 +684,7 @@
   EXPECT_TRUE(overlapping_apps_b.empty());
 }
 
-TEST_F(AppManagementPageHandlerTestBase, UseCase_ADisabledBEnabled) {
+TEST_P(AppManagementPageHandlerTestBase, UseCase_ADisabledBEnabled) {
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info1->title = u"A";
   web_app_info1->start_url = GURL("https://example.com/index.html");
@@ -670,7 +716,7 @@
   EXPECT_TRUE(overlapping_apps_b.empty());
 }
 
-TEST_F(AppManagementPageHandlerTestBase, UseCase_AEnabledBDisabled) {
+TEST_P(AppManagementPageHandlerTestBase, UseCase_AEnabledBDisabled) {
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info1->title = u"A";
   web_app_info1->start_url = GURL("https://example.com/index.html");
@@ -702,7 +748,7 @@
   EXPECT_THAT(overlapping_apps_b, testing::ElementsAre(appA));
 }
 
-TEST_F(AppManagementPageHandlerTestBase, UseCase_AEnabledBEnabled) {
+TEST_P(AppManagementPageHandlerTestBase, UseCase_AEnabledBEnabled) {
   auto web_app_info1 = std::make_unique<web_app::WebAppInstallInfo>();
   web_app_info1->title = u"A";
   web_app_info1->start_url = GURL("https://example.com/index.html");
@@ -757,6 +803,7 @@
   void TearDown() override {
     arc_test_.StopArcInstance();
     arc_test_.TearDown();
+    AppManagementPageHandlerTestBase::TearDown();
   }
 
  protected:
@@ -766,7 +813,7 @@
   ArcAppTest arc_test_;
 };
 
-TEST_F(AppManagementPageHandlerArcTest, OpenStorePageArcAppPlayStore) {
+TEST_P(AppManagementPageHandlerArcTest, OpenStorePageArcAppPlayStore) {
   const auto& fake_apps = arc_test()->fake_apps();
   std::string package_name = fake_apps[1]->package_name;
   std::string app_id = ArcAppListPrefs::GetAppId(fake_apps[1]->package_name,
@@ -790,7 +837,7 @@
                 fake_apps[1]->package_name);
 }
 
-TEST_F(AppManagementPageHandlerArcTest, OpenStorePageWebAppPlayStore) {
+TEST_P(AppManagementPageHandlerArcTest, OpenStorePageWebAppPlayStore) {
   std::vector<arc::mojom::ArcPackageInfoPtr> packages;
   auto package = arc::mojom::ArcPackageInfo::New();
   package->package_name = "package_name";
@@ -827,6 +874,26 @@
   EXPECT_EQ(intents[0].intent->data.value(),
             "https://play.google.com/store/apps/details?id=package_name");
 }
+
+INSTANTIATE_TEST_SUITE_P(,
+                         AppManagementPageHandlerArcTest,
+                         testing::Values(false),
+                         [](const testing::TestParamInfo<bool>& info) {
+                           return info.param ? "CapturingDefaultOn"
+                                             : "CapturingDefaultOff";
+                         });
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+INSTANTIATE_TEST_SUITE_P(,
+                         AppManagementPageHandlerTestBase,
+#if BUILDFLAG(IS_CHROMEOS)
+                         testing::Values(false),
+#else
+                         testing::Values(true, false),
+#endif
+                         [](const testing::TestParamInfo<bool>& info) {
+                           return info.param ? "CapturingDefaultOn"
+                                             : "CapturingDefaultOff";
+                         });
+
 }  // namespace apps
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc
index 63f3962..e84f955 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc
@@ -419,6 +419,7 @@
             case OfficeFilesSourceVolume::kGuestOS:
             case OfficeFilesSourceVolume::kUnknown:
             case OfficeFilesSourceVolume::kMicrosoftOneDrive:
+            case OfficeFilesSourceVolume::kAndroidOneDriveDocumentsProvider:
               SetWrongValueLogged(source_volume);
               break;
           }
@@ -428,6 +429,7 @@
         if (source_volume.logged()) {
           switch (source_volume.value) {
             case OfficeFilesSourceVolume::kMicrosoftOneDrive:
+            case OfficeFilesSourceVolume::kAndroidOneDriveDocumentsProvider:
               break;
             case OfficeFilesSourceVolume::kDownloadsDirectory:
             case OfficeFilesSourceVolume::kRemovableDiskPartition:
@@ -473,6 +475,7 @@
             case OfficeFilesSourceVolume::kGuestOS:
             case OfficeFilesSourceVolume::kUnknown:
             case OfficeFilesSourceVolume::kMicrosoftOneDrive:
+            case OfficeFilesSourceVolume::kAndroidOneDriveDocumentsProvider:
               break;
             case OfficeFilesSourceVolume::kGoogleDrive:
               SetWrongValueLogged(source_volume);
@@ -498,6 +501,7 @@
             case OfficeFilesSourceVolume::kGoogleDrive:
               break;
             case OfficeFilesSourceVolume::kMicrosoftOneDrive:
+            case OfficeFilesSourceVolume::kAndroidOneDriveDocumentsProvider:
               SetWrongValueLogged(source_volume);
               break;
           }
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics_unittest.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics_unittest.cc
index e95b1b4..ab147ab 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics_unittest.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics_unittest.cc
@@ -612,6 +612,56 @@
   ASSERT_EQ(0, CloudOpenMetricsTest::number_of_dump_calls());
 }
 
+// Tests that the SourceVolume companion metric is set correctly when
+// TransferRequired is logged as kNotRequired and the file is opened from
+// Android Documents Provider with M365.
+TEST_F(
+    CloudOpenMetricsTest,
+    NoDumpWhenAllMetricsAreConsistentForOpenFlowFromAndroidDocumentsProvider) {
+  {
+    CloudOpenMetrics cloud_open_metrics(CloudProvider::kOneDrive,
+                                        /*file_count=*/1);
+    cloud_open_metrics.LogSourceVolume(
+        OfficeFilesSourceVolume::kAndroidOneDriveDocumentsProvider);
+    cloud_open_metrics.LogTransferRequired(
+        OfficeFilesTransferRequired::kNotRequired);
+    cloud_open_metrics.LogTaskResult(OfficeTaskResult::kOpened);
+    cloud_open_metrics.LogOneDriveOpenError(OfficeOneDriveOpenErrors::kSuccess);
+  }
+  histogram_.ExpectUniqueSample(kOneDriveCopyErrorMetricStateMetricName,
+                                MetricState::kCorrectlyNotLogged, 1);
+  histogram_.ExpectUniqueSample(kOneDriveMoveErrorMetricStateMetricName,
+                                MetricState::kCorrectlyNotLogged, 1);
+  histogram_.ExpectUniqueSample(kOneDriveErrorMetricStateMetricName,
+                                MetricState::kCorrectlyLogged, 1);
+  histogram_.ExpectUniqueSample(kOneDriveOpenSourceVolumeMetricStateMetric,
+                                MetricState::kCorrectlyLogged, 1);
+  histogram_.ExpectUniqueSample(kOneDriveTaskResultMetricStateMetricName,
+                                MetricState::kCorrectlyLogged, 1);
+  histogram_.ExpectUniqueSample(kOneDriveTransferRequiredMetricStateMetric,
+                                MetricState::kCorrectlyLogged, 1);
+  histogram_.ExpectUniqueSample(kOneDriveUploadResultMetricStateMetricName,
+                                MetricState::kCorrectlyNotLogged, 1);
+
+  // No Google Drive metrics should be logged.
+  histogram_.ExpectUniqueSample(kGoogleDriveCopyErrorMetricStateMetricName,
+                                MetricState::kCorrectlyNotLogged, 1);
+  histogram_.ExpectUniqueSample(kGoogleDriveMoveErrorMetricStateMetricName,
+                                MetricState::kCorrectlyNotLogged, 1);
+  histogram_.ExpectUniqueSample(kDriveErrorMetricStateMetricName,
+                                MetricState::kCorrectlyNotLogged, 1);
+  histogram_.ExpectUniqueSample(kDriveOpenSourceVolumeMetricStateMetric,
+                                MetricState::kCorrectlyNotLogged, 1);
+  histogram_.ExpectUniqueSample(kGoogleDriveTaskResultMetricStateMetricName,
+                                MetricState::kCorrectlyNotLogged, 1);
+  histogram_.ExpectUniqueSample(kDriveTransferRequiredMetricStateMetric,
+                                MetricState::kCorrectlyNotLogged, 1);
+  histogram_.ExpectUniqueSample(kGoogleDriveUploadResultMetricStateMetricName,
+                                MetricState::kCorrectlyNotLogged, 1);
+
+  ASSERT_EQ(0, CloudOpenMetricsTest::number_of_dump_calls());
+}
+
 // Tests that when all metrics are consistent for the cloud upload flow, there
 // is no dump without crashing.
 TEST_F(CloudOpenMetricsTest, NoDumpWhenAllMetricsAreConsistentForMoveFlow) {
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc
index 43f0de2..7ea313b 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc
@@ -446,6 +446,8 @@
   OfficeFilesSourceVolume source_volume;
   if (UrlIsOnODFS(profile_, file_urls_.front())) {
     source_volume = OfficeFilesSourceVolume::kMicrosoftOneDrive;
+  } else if (UrlIsOnAndroidOneDrive(profile_, file_urls_.front())) {
+    source_volume = OfficeFilesSourceVolume::kAndroidOneDriveDocumentsProvider;
   } else {
     auto* volume_manager = file_manager::VolumeManager::Get(profile_);
     base::WeakPtr<file_manager::Volume> source =
@@ -466,14 +468,15 @@
         OfficeFilesTransferRequired::kNotRequired);
     OpenAlreadyHostedDriveUrls();
   } else if (cloud_provider_ == CloudProvider::kOneDrive &&
-             UrlIsOnODFS(profile_, file_urls_.front())) {
+             source_volume == OfficeFilesSourceVolume::kMicrosoftOneDrive) {
     // The files are on OneDrive already, selected from ODFS.
     transfer_required_ = OfficeFilesTransferRequired::kNotRequired;
     cloud_open_metrics_->LogTransferRequired(
         OfficeFilesTransferRequired::kNotRequired);
     OpenODFSUrls(OfficeTaskResult::kOpened);
   } else if (cloud_provider_ == CloudProvider::kOneDrive &&
-             UrlIsOnAndroidOneDrive(profile_, file_urls_.front())) {
+             source_volume ==
+                 OfficeFilesSourceVolume::kAndroidOneDriveDocumentsProvider) {
     // The files are on OneDrive already, selected from Android OneDrive.
     transfer_required_ = OfficeFilesTransferRequired::kNotRequired;
     cloud_open_metrics_->LogTransferRequired(
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h
index 0a5be21..3bb235721 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h
@@ -137,7 +137,8 @@
   kGuestOS = 12,         // Guest OS volumes (Crostini, Bruschetta, etc)
   kUnknown = 100,
   kMicrosoftOneDrive = 101,
-  kMaxValue = kMicrosoftOneDrive,
+  kAndroidOneDriveDocumentsProvider = 102,
+  kMaxValue = kAndroidOneDriveDocumentsProvider,
 };
 
 // List of UMA enum value for Web Drive Office task results. The enum values
diff --git a/chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.cc b/chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.cc
index 5020bb71..fda94fb 100644
--- a/chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.cc
+++ b/chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.cc
@@ -5,10 +5,12 @@
 #include "chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.h"
 
 #include <memory>
+#include <string_view>
 #include <utility>
 
 #include "ash/public/cpp/login_screen.h"
 #include "base/values.h"
+#include "chrome/browser/ash/app_mode/kiosk_app.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager_base.h"
 #include "chrome/browser/ash/login/oobe_screen.h"
@@ -24,36 +26,38 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/webui/web_ui_util.h"
+#include "ui/gfx/image/image_skia.h"
+#include "url/gurl.h"
 
 namespace ash {
 
 namespace {
 
-base::Value::Dict ConvertAppToDict(KioskAppManagerBase::App app) {
-  base::Value::Dict out_info;
+std::string NameOrDefault(std::string_view name) {
+  return name.empty() ? l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME)
+                      : std::string(name);
+}
 
-  if (app.name.empty()) {
-    app.name = l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME);
-  }
-
-  if (app.icon.isNull()) {
-    app.icon = *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-        IDR_PRODUCT_LOGO_128);
-  }
-
-  // Display app domain if present.
-  if (!app.url.is_empty()) {
-    app.url = app.url.DeprecatedGetOriginAsURL();
-  }
-
-  out_info.Set("name", app.name);
-  out_info.Set("iconURL", webui::GetBitmapDataUrl(*app.icon.bitmap()));
-  out_info.Set("url", app.url.spec());
-  return out_info;
+gfx::ImageSkia IconOrDefault(gfx::ImageSkia icon) {
+  return icon.isNull()
+             ? *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+                   IDR_PRODUCT_LOGO_128)
+             : icon;
 }
 
 }  // namespace
 
+AppLaunchSplashScreenView::Data::Data(std::string_view name,
+                                      gfx::ImageSkia icon,
+                                      const GURL& url)
+    : name(NameOrDefault(name)),
+      icon(IconOrDefault(icon)),
+      url(url.DeprecatedGetOriginAsURL()) {}
+AppLaunchSplashScreenView::Data::Data(Data&&) = default;
+AppLaunchSplashScreenView::Data& AppLaunchSplashScreenView::Data::operator=(
+    Data&&) = default;
+AppLaunchSplashScreenView::Data::~Data() = default;
+
 AppLaunchSplashScreenHandler::AppLaunchSplashScreenHandler(
     const scoped_refptr<NetworkStateInformer>& network_state_informer,
     ErrorScreen* error_screen)
@@ -73,17 +77,21 @@
                                           product_os_name));
 }
 
-void AppLaunchSplashScreenHandler::Show(KioskAppManagerBase::App app_data) {
+void AppLaunchSplashScreenHandler::Show(Data data) {
   is_shown_ = true;
 
-  base::Value::Dict data;
-  data.Set("shortcutEnabled",
-           !KioskAppManager::Get()->GetDisableBailoutShortcut());
-
-  data.Set("appInfo", ConvertAppToDict(app_data));
+  base::Value::Dict dict =
+      base::Value::Dict()
+          .Set("shortcutEnabled",
+               !KioskAppManager::Get()->GetDisableBailoutShortcut())
+          .Set("appInfo",
+               base::Value::Dict()
+                   .Set("name", data.name)
+                   .Set("iconURL", webui::GetBitmapDataUrl(*data.icon.bitmap()))
+                   .Set("url", data.url.spec()));
 
   SetLaunchText(l10n_util::GetStringUTF8(GetProgressMessageFromState(state_)));
-  ShowInWebUI(std::move(data));
+  ShowInWebUI(std::move(dict));
   if (toggle_network_config_on_show_.has_value()) {
     DoToggleNetworkConfig(toggle_network_config_on_show_.value());
     toggle_network_config_on_show_.reset();
diff --git a/chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.h b/chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.h
index bd858c9..177cf45 100644
--- a/chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.h
+++ b/chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.h
@@ -7,14 +7,18 @@
 
 #include <set>
 #include <string>
+#include <string_view>
 
 #include "base/memory/raw_ptr.h"
+#include "chrome/browser/ash/app_mode/kiosk_app.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_launch_error.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager_base.h"
 #include "chrome/browser/ash/login/screens/error_screen.h"
 #include "chrome/browser/ui/webui/ash/login/base_screen_handler.h"
 #include "chrome/browser/ui/webui/ash/login/network_state_informer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/image/image_skia.h"
+#include "url/gurl.h"
 
 namespace ash {
 
@@ -30,6 +34,23 @@
     virtual void OnNetworkConfigFinished() {}
   };
 
+  // The data struct needed to populate this view.
+  struct Data {
+    Data(std::string_view name, gfx::ImageSkia icon, const GURL& url);
+    Data(const Data&) = delete;
+    Data(Data&&);
+    Data& operator=(const Data&) = delete;
+    Data& operator=(Data&&);
+    ~Data();
+
+    // The name of the app.
+    std::string name;
+    // The icon of the app.
+    gfx::ImageSkia icon;
+    // The URL of the app.
+    GURL url;
+  };
+
   enum class AppLaunchState {
     kPreparingProfile,
     kPreparingNetwork,
@@ -49,8 +70,8 @@
   // Sets screen controller this view belongs to.
   virtual void SetDelegate(Delegate* delegate) = 0;
 
-  // Shows the contents of the screen.
-  virtual void Show(KioskAppManagerBase::App app_data) = 0;
+  // Shows or updates the contents of the screen with the given `data`.
+  virtual void Show(Data data) = 0;
 
   // Hides the contents of the screen.
   virtual void Hide() = 0;
@@ -94,7 +115,7 @@
   void DeclareJSCallbacks() override;
 
   // AppLaunchSplashScreenView implementation:
-  void Show(KioskAppManagerBase::App app_data) override;
+  void Show(Data data) override;
   void Hide() override;
   void ToggleNetworkConfig(bool visible) override;
   void UpdateAppLaunchState(AppLaunchState state) override;
diff --git a/chrome/browser/ui/webui/ash/login/fake_app_launch_splash_screen_handler.cc b/chrome/browser/ui/webui/ash/login/fake_app_launch_splash_screen_handler.cc
index 9830c0d5..a2cc041 100644
--- a/chrome/browser/ui/webui/ash/login/fake_app_launch_splash_screen_handler.cc
+++ b/chrome/browser/ui/webui/ash/login/fake_app_launch_splash_screen_handler.cc
@@ -11,8 +11,8 @@
   delegate_ = delegate;
 }
 
-void FakeAppLaunchSplashScreenHandler::Show(KioskAppManagerBase::App app_data) {
-  last_app_data_ = app_data;
+void FakeAppLaunchSplashScreenHandler::Show(Data data) {
+  last_data_ = std::move(data);
 }
 
 void FakeAppLaunchSplashScreenHandler::ShowErrorMessage(
diff --git a/chrome/browser/ui/webui/ash/login/fake_app_launch_splash_screen_handler.h b/chrome/browser/ui/webui/ash/login/fake_app_launch_splash_screen_handler.h
index 8c742a8..95602cc 100644
--- a/chrome/browser/ui/webui/ash/login/fake_app_launch_splash_screen_handler.h
+++ b/chrome/browser/ui/webui/ash/login/fake_app_launch_splash_screen_handler.h
@@ -7,6 +7,8 @@
 
 #include "chrome/browser/ash/app_mode/kiosk_app_manager_base.h"
 #include "chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.h"
+#include "ui/gfx/image/image_skia.h"
+#include "url/gurl.h"
 
 namespace ash {
 
@@ -14,7 +16,7 @@
 class FakeAppLaunchSplashScreenHandler : public AppLaunchSplashScreenView {
  public:
   void SetDelegate(Delegate*) override;
-  void Show(KioskAppManagerBase::App app_data) override;
+  void Show(Data data) override;
   void Hide() override {}
   void UpdateAppLaunchState(AppLaunchState state) override;
   void ToggleNetworkConfig(bool) override {}
@@ -27,13 +29,15 @@
   void FinishNetworkConfig();
   AppLaunchState GetAppLaunchState() const;
   bool IsNetworkRequired() const;
-  KioskAppManagerBase::App last_app_data() const { return last_app_data_; }
+  const Data& last_data() const { return last_data_; }
 
  private:
   raw_ptr<Delegate> delegate_ = nullptr;
   KioskAppLaunchError::Error error_message_type_ =
       KioskAppLaunchError::Error::kNone;
-  KioskAppManagerBase::App last_app_data_;
+  Data last_data_ = Data(/*name=*/"no data received yet",
+                         /*icon=*/gfx::ImageSkia(),
+                         /*url=*/GURL());
   AppLaunchState state_ = AppLaunchState::kPreparingProfile;
 };
 
diff --git a/chrome/browser/ui/webui/ash/settings/pages/a11y/accessibility_section.cc b/chrome/browser/ui/webui/ash/settings/pages/a11y/accessibility_section.cc
index ac15aab..e76919c 100644
--- a/chrome/browser/ui/webui/ash/settings/pages/a11y/accessibility_section.cc
+++ b/chrome/browser/ui/webui/ash/settings/pages/a11y/accessibility_section.cc
@@ -519,6 +519,8 @@
   webui::LocalizedString kLocalizedStrings[] = {
       {"a11yExplanation", IDS_SETTINGS_ACCESSIBILITY_EXPLANATION},
       {"a11yPageTitle", IDS_SETTINGS_ACCESSIBILITY},
+      {"a11yMenuItemDescription",
+       IDS_OS_SETTINGS_ACCESSIBILITY_MENU_ITEM_DESCRIPTION},
       {"a11yWebStore", IDS_SETTINGS_ACCESSIBILITY_WEB_STORE},
       {"accessibleImageLabelsSubtitle",
        IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_SUBTITLE},
diff --git a/chrome/browser/ui/webui/ash/settings/pages/internet/internet_section.cc b/chrome/browser/ui/webui/ash/settings/pages/internet/internet_section.cc
index 9d0b080..e6e1052f 100644
--- a/chrome/browser/ui/webui/ash/settings/pages/internet/internet_section.cc
+++ b/chrome/browser/ui/webui/ash/settings/pages/internet/internet_section.cc
@@ -302,12 +302,6 @@
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
        {.setting = mojom::Setting::kCellularRoaming}},
-      {IDS_OS_SETTINGS_TAG_CELLULAR_APN,
-       mojom::kCellularDetailsSubpagePath,
-       mojom::SearchResultIcon::kCellular,
-       mojom::SearchResultDefaultRank::kMedium,
-       mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kCellularApn}},
   });
   return *tags;
 }
@@ -399,6 +393,39 @@
 }
 
 const std::vector<SearchConcept>&
+GeActiveCellularNetworkApnSettingsSearchConcepts() {
+  if (ash::features::IsApnRevampEnabled()) {
+    static const base::NoDestructor<std::vector<SearchConcept>> tags(
+        {{IDS_OS_SETTINGS_TAG_CELLULAR_APN_SETTINGS,
+          mojom::kApnSubpagePath,
+          mojom::SearchResultIcon::kCellular,
+          mojom::SearchResultDefaultRank::kMedium,
+          mojom::SearchResultType::kSubpage,
+          {.subpage = mojom::Subpage::kApn},
+          {IDS_OS_SETTINGS_TAG_CELLULAR_APN_SETTINGS_ALT_1,
+           SearchConcept::kAltTagEnd}},
+         {IDS_OS_SETTINGS_TAG_ADD_APN,
+          mojom::kApnSubpagePath,
+          mojom::SearchResultIcon::kCellular,
+          mojom::SearchResultDefaultRank::kMedium,
+          mojom::SearchResultType::kSetting,
+          {.setting = mojom::Setting::kCellularAddApn},
+          {IDS_OS_SETTINGS_TAG_ADD_APN_ALT1, SearchConcept::kAltTagEnd}}});
+    return *tags;
+  }
+
+  static const base::NoDestructor<std::vector<SearchConcept>> tags({
+      {IDS_OS_SETTINGS_TAG_CELLULAR_APN,
+       mojom::kCellularDetailsSubpagePath,
+       mojom::SearchResultIcon::kCellular,
+       mojom::SearchResultDefaultRank::kMedium,
+       mojom::SearchResultType::kSetting,
+       {.setting = mojom::Setting::kCellularApn}},
+  });
+  return *tags;
+}
+
+const std::vector<SearchConcept>&
 GetCellularPrimaryIsNonPolicyESimSearchConcepts() {
   static const base::NoDestructor<std::vector<SearchConcept>> tags({
       {IDS_OS_SETTINGS_TAG_CELLULAR_REMOVE_PROFILE,
@@ -602,6 +629,7 @@
       mojom::Setting::kCellularMetered,
       mojom::Setting::kCellularRemoveESimNetwork,
       mojom::Setting::kCellularRenameESimNetwork,
+      mojom::Setting::kCellularAddApn,
   });
   return *settings;
 }
@@ -1340,6 +1368,10 @@
     return GetDetailsSubpageUrl(modified_url, *active_cellular_guid_);
   }
 
+  if (IsPartOfDetailsSubpage(type, id, mojom::Subpage::kApn)) {
+    return GetDetailsSubpageUrl(modified_url, *active_cellular_guid_);
+  }
+
   if (IsPartOfDetailsSubpage(type, id, mojom::Subpage::kTetherDetails)) {
     return GetDetailsSubpageUrl(modified_url, *connected_tether_guid_);
   }
@@ -1503,6 +1535,7 @@
   updater.RemoveSearchTags(GetWifiMeteredSearchConcepts());
   updater.RemoveSearchTags(GetWifiHiddenSearchConcepts());
   updater.RemoveSearchTags(GetCellularSearchConcepts());
+  updater.RemoveSearchTags(GeActiveCellularNetworkApnSettingsSearchConcepts());
   updater.RemoveSearchTags(GetCellularConnectedSearchConcepts());
   updater.RemoveSearchTags(GetCellularPrimaryIsNonPolicyESimSearchConcepts());
   updater.RemoveSearchTags(GetCellularMeteredSearchConcepts());
@@ -1527,6 +1560,8 @@
       if (is_primary_cellular_network) {
         active_cellular_guid_ = network->guid;
         updater.AddSearchTags(GetCellularSearchConcepts());
+        updater.AddSearchTags(
+            GeActiveCellularNetworkApnSettingsSearchConcepts());
 
         // If the primary cellular network is ESim and not policy ESim.
         if (!network->type_state->get_cellular()->eid.empty() &&
diff --git a/chrome/browser/ui/webui/ash/shortcut_customization/BUILD.gn b/chrome/browser/ui/webui/ash/shortcut_customization/BUILD.gn
new file mode 100644
index 0000000..968d6e88
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/shortcut_customization/BUILD.gn
@@ -0,0 +1,29 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/chromeos/ui_mode.gni")
+
+assert(is_chromeos_ash)
+
+static_library("test_support") {
+  testonly = true
+  sources = [
+    "shortcut_customization_test_base.cc",
+    "shortcut_customization_test_base.h",
+  ]
+  deps = [
+    "//ash:test_support",
+    "//ash/public/cpp",
+    "//base/test:test_support",
+    "//chrome/browser",
+    "//chrome/browser/ash",
+    "//chrome/browser/ash:test_support",
+    "//chrome/browser/ash/system_web_apps/test_support:test_support_ui",
+    "//chrome/browser/ui",
+    "//chrome/test:test_support_ui",
+    "//ui/base",
+    "//ui/events",
+    "//ui/views",
+  ]
+}
diff --git a/chrome/browser/ui/webui/ash/shortcut_customization/integration_tests/add_custom_accelerator_and_reset_interactive_uitest.cc b/chrome/browser/ui/webui/ash/shortcut_customization/integration_tests/add_custom_accelerator_and_reset_interactive_uitest.cc
index bca193a7..5e77084 100644
--- a/chrome/browser/ui/webui/ash/shortcut_customization/integration_tests/add_custom_accelerator_and_reset_interactive_uitest.cc
+++ b/chrome/browser/ui/webui/ash/shortcut_customization/integration_tests/add_custom_accelerator_and_reset_interactive_uitest.cc
@@ -5,10 +5,8 @@
 #include <linux/input-event-codes.h>
 
 #include "ash/ash_element_identifiers.h"
-#include "ash/webui/system_apps/public/system_web_app_type.h"
-#include "base/test/scoped_feature_list.h"
-#include "chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
+#include "chrome/browser/ui/webui/ash/shortcut_customization/shortcut_customization_test_base.h"
 #include "chrome/test/base/chromeos/crosier/interactive_ash_test.h"
 #include "chrome/test/interaction/interactive_browser_test.h"
 #include "ui/base/interaction/element_identifier.h"
@@ -19,145 +17,42 @@
 
 namespace {
 
-constexpr char kClickFn[] = "e => e.click()";
-constexpr char kFocusFn[] = "e => e.focus()";
-
-class ShortcutCustomizationInteractiveUiTest
-    : public SystemWebAppBrowserTestBase {
- public:
-  ShortcutCustomizationInteractiveUiTest() {
-    feature_list_.InitWithFeatures({::features::kShortcutCustomization,
-                                    ::features::kShortcutCustomizationApp},
-                                   {});
-  }
-
-  auto LaunchShortcutCustomizationApp() {
-    return Do([&]() {
-      LaunchApp(
-          LaunchParamsForApp(ash::SystemWebAppType::SHORTCUT_CUSTOMIZATION));
-    });
-  }
-
-  // Query to pierce through Shadow DOM to find the keyboard.
-  const DeepQuery kEditButtonQuery{
-      "shortcut-customization-app",
-      "navigation-view-panel#navigationPanel",
-      "#category-0",
-      "#container",
-      "accelerator-subsection",
-      "tbody#rowList",
-      // Action 93 corresponds to the "Open/Close Calendar" shortcut.
-      "accelerator-row[action='93']",
-      "cr-icon-button.edit-button",
-  };
-
-  const DeepQuery kCalendarAcceleratorRowQuery{
-      "shortcut-customization-app",
-      "navigation-view-panel#navigationPanel",
-      "#category-0",
-      "#container",
-      "accelerator-subsection",
-      "tbody#rowList",
-      // Action 93 corresponds to the "Open/Close Calendar" shortcut.
-      "accelerator-row[action='93']",
-  };
-
-  const DeepQuery kAddShortcutButtonQuery{
-      "shortcut-customization-app",
-      "#editDialog",
-      "#addAcceleratorButton",
-  };
-
-  const DeepQuery kDoneButtonQuery{
-      "shortcut-customization-app",
-      "#editDialog",
-      "#doneButton",
-  };
-
-  const DeepQuery kRestoreDefaultsButtonQuery{
-      "shortcut-customization-app",
-      "#editDialog",
-      "#restoreDefault",
-  };
-
-  auto OpenCalendarShortcutDialog() {
-    return Steps(
-        ExecuteJsAt(webcontents_id, kCalendarAcceleratorRowQuery, kFocusFn),
-        ExecuteJsAt(webcontents_id, kEditButtonQuery, kClickFn));
-  }
-
-  auto AddCustomCalendarShortcut(ui::Accelerator new_accel) {
-    return Steps(ExecuteJsAt(webcontents_id, kAddShortcutButtonQuery, kClickFn),
-                 InAnyContext(SendAccelerator(webcontents_id, new_accel)),
-                 ExecuteJsAt(webcontents_id, kDoneButtonQuery, kClickFn));
-  }
-
-  auto ResetCalendarShortcuts() {
-    return Steps(
-        ExecuteJsAt(webcontents_id, kCalendarAcceleratorRowQuery, kFocusFn),
-        ExecuteJsAt(webcontents_id, kEditButtonQuery, kClickFn),
-        ExecuteJsAt(webcontents_id, kRestoreDefaultsButtonQuery, kClickFn),
-        ExecuteJsAt(webcontents_id, kDoneButtonQuery, kClickFn));
-  }
-
-  // Ensure focusing web contents doesn't accidentally block accelerator
-  // processing. When adding new accelerators, this method is called to
-  // prevent the system from processing Ash accelerators.
-  ui::InteractionSequence::StepBuilder EnsureAcceleratorsAreProcessed() {
-    return ExecuteJs(webcontents_id,
-                     "() => "
-                     "document.querySelector('shortcut-customization-app')."
-                     "shortcutProvider.preventProcessingAccelerators(false)");
-  }
-
-  void SetUpOnMainThread() override {
-    SystemWebAppBrowserTestBase::SetUpOnMainThread();
-
-    // Ensure the Shortcut Customization system web app (SWA) is installed.
-    WaitForTestSystemAppInstall();
-  }
-
- protected:
-  base::test::ScopedFeatureList feature_list_;
-  ui::ElementIdentifier webcontents_id;
-};
-
-IN_PROC_BROWSER_TEST_F(ShortcutCustomizationInteractiveUiTest,
+IN_PROC_BROWSER_TEST_F(ShortcutCustomizationInteractiveUiTestBase,
                        AddCustomAcceleratorAndReset) {
   ui::Accelerator default_accel(ui::VKEY_C, ui::EF_COMMAND_DOWN);
   ui::Accelerator new_accel(ui::VKEY_N,
                             ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN);
 
   DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kShortcutAppWebContentsId);
-  webcontents_id = kShortcutAppWebContentsId;
+  webcontents_id_ = kShortcutAppWebContentsId;
   RunTestSequence(
       InstrumentNextTab(kShortcutAppWebContentsId, AnyBrowser()),
       LaunchShortcutCustomizationApp(),
       WaitForWebContentsReady(kShortcutAppWebContentsId,
                               GURL("chrome://shortcut-customization")),
       InAnyContext(Steps(
-          SendAccelerator(webcontents_id, new_accel),
+          SendAccelerator(webcontents_id_, new_accel),
           EnsureNotPresent(kCalendarViewElementId),
           Log("Verify that the custom shortcut does not open the calendar "
               "before it's added as a shortcut"),
           OpenCalendarShortcutDialog(), AddCustomCalendarShortcut(new_accel),
           Log("Adding Search + Ctrl + n as a custom open/close calendar "
               "shortcut"),
-          FocusWebContents(webcontents_id), EnsureAcceleratorsAreProcessed(),
-          SendAccelerator(webcontents_id, new_accel), FlushEvents(),
+          FocusWebContents(webcontents_id_), EnsureAcceleratorsAreProcessed(),
+          SendAccelerator(webcontents_id_, new_accel), FlushEvents(),
           WaitForShow(kCalendarViewElementId),
           Log("Custom shortcut opens calendar"),
-          SendAccelerator(webcontents_id, new_accel), FlushEvents(),
+          SendAccelerator(webcontents_id_, new_accel), FlushEvents(),
           WaitForHide(kCalendarViewElementId),
           Log("Custom shortcut closes calendar"), ResetCalendarShortcuts(),
           Log("Open/Close calendar shortcut reset to defaults"),
-          FocusWebContents(webcontents_id), EnsureAcceleratorsAreProcessed(),
-          SendAccelerator(webcontents_id, default_accel), FlushEvents(),
+          FocusWebContents(webcontents_id_), EnsureAcceleratorsAreProcessed(),
+          SendAccelerator(webcontents_id_, default_accel), FlushEvents(),
           WaitForShow(kCalendarViewElementId),
-          SendAccelerator(webcontents_id, default_accel), FlushEvents(),
+          SendAccelerator(webcontents_id_, default_accel), FlushEvents(),
           WaitForHide(kCalendarViewElementId),
           Log("Default shortcut still works"),
-          SendAccelerator(webcontents_id, new_accel), FlushEvents(),
+          SendAccelerator(webcontents_id_, new_accel), FlushEvents(),
           EnsureNotPresent(kCalendarViewElementId),
           Log("Custom shortcut no longer works"))));
 }
diff --git a/chrome/browser/ui/webui/ash/shortcut_customization/shortcut_customization_test_base.cc b/chrome/browser/ui/webui/ash/shortcut_customization/shortcut_customization_test_base.cc
new file mode 100644
index 0000000..33b0f39
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/shortcut_customization/shortcut_customization_test_base.cc
@@ -0,0 +1,49 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/ash/shortcut_customization/shortcut_customization_test_base.h"
+
+#include "ash/webui/system_apps/public/system_web_app_type.h"
+#include "chrome/test/interaction/interactive_browser_test.h"
+#include "ui/base/interaction/interaction_sequence.h"
+
+namespace ash {
+
+ShortcutCustomizationInteractiveUiTestBase::
+    ShortcutCustomizationInteractiveUiTestBase() {
+  feature_list_.InitWithFeatures({::features::kShortcutCustomization,
+                                  ::features::kShortcutCustomizationApp},
+                                 {});
+}
+
+ShortcutCustomizationInteractiveUiTestBase::
+    ~ShortcutCustomizationInteractiveUiTestBase() = default;
+
+void ShortcutCustomizationInteractiveUiTestBase::SetUpOnMainThread() {
+  SystemWebAppBrowserTestBase::SetUpOnMainThread();
+  // Ensure the Shortcut Customization system web app (SWA) is installed.
+  WaitForTestSystemAppInstall();
+}
+
+ui::InteractionSequence::StepBuilder
+ShortcutCustomizationInteractiveUiTestBase::LaunchShortcutCustomizationApp() {
+  return Do([&]() {
+    LaunchApp(
+        LaunchParamsForApp(ash::SystemWebAppType::SHORTCUT_CUSTOMIZATION));
+  });
+}
+
+// Ensure focusing web contents doesn't accidentally block accelerator
+// processing. When adding new accelerators, this method is called to
+// prevent the system from processing Ash accelerators.
+ui::InteractionSequence::StepBuilder
+ShortcutCustomizationInteractiveUiTestBase::EnsureAcceleratorsAreProcessed() {
+  CHECK(webcontents_id_);
+  return ExecuteJs(webcontents_id_,
+                   "() => "
+                   "document.querySelector('shortcut-customization-app')."
+                   "shortcutProvider.preventProcessingAccelerators(false)");
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ui/webui/ash/shortcut_customization/shortcut_customization_test_base.h b/chrome/browser/ui/webui/ash/shortcut_customization/shortcut_customization_test_base.h
new file mode 100644
index 0000000..bda9929
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/shortcut_customization/shortcut_customization_test_base.h
@@ -0,0 +1,118 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_ASH_SHORTCUT_CUSTOMIZATION_SHORTCUT_CUSTOMIZATION_TEST_BASE_H_
+#define CHROME_BROWSER_UI_WEBUI_ASH_SHORTCUT_CUSTOMIZATION_SHORTCUT_CUSTOMIZATION_TEST_BASE_H_
+
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.h"
+#include "ui/base/interaction/interaction_sequence.h"
+
+namespace ash {
+
+inline constexpr char kClickFn[] = "e => e.click()";
+inline constexpr char kFocusFn[] = "e => e.focus()";
+
+class ShortcutCustomizationInteractiveUiTestBase
+    : public SystemWebAppBrowserTestBase {
+ public:
+  ShortcutCustomizationInteractiveUiTestBase();
+
+  ShortcutCustomizationInteractiveUiTestBase(
+      const ShortcutCustomizationInteractiveUiTestBase&) = delete;
+  ShortcutCustomizationInteractiveUiTestBase& operator=(
+      const ShortcutCustomizationInteractiveUiTestBase&) = delete;
+  ~ShortcutCustomizationInteractiveUiTestBase() override;
+
+  // Query to pierce through Shadow DOM to find the keyboard.
+  const DeepQuery kEditButtonQuery{
+      "shortcut-customization-app",
+      "navigation-view-panel#navigationPanel",
+      "#category-0",
+      "#container",
+      "accelerator-subsection",
+      "tbody#rowList",
+      // Action 93 corresponds to the "Open/Close Calendar" shortcut.
+      "accelerator-row[action='93']",
+      "cr-icon-button.edit-button",
+  };
+
+  const DeepQuery kCalendarAcceleratorRowQuery{
+      "shortcut-customization-app",
+      "navigation-view-panel#navigationPanel",
+      "#category-0",
+      "#container",
+      "accelerator-subsection",
+      "tbody#rowList",
+      // Action 93 corresponds to the "Open/Close Calendar" shortcut.
+      "accelerator-row[action='93']",
+  };
+
+  const DeepQuery kAddShortcutButtonQuery{
+      "shortcut-customization-app",
+      "#editDialog",
+      "#addAcceleratorButton",
+  };
+
+  const DeepQuery kDoneButtonQuery{
+      "shortcut-customization-app",
+      "#editDialog",
+      "#doneButton",
+  };
+
+  const DeepQuery kRestoreDefaultsButtonQuery{
+      "shortcut-customization-app",
+      "#editDialog",
+      "#restoreDefault",
+  };
+
+  auto OpenCalendarShortcutDialog() {
+    CHECK(webcontents_id_);
+    return Steps(
+        ExecuteJsAt(webcontents_id_, kCalendarAcceleratorRowQuery, kFocusFn),
+        ExecuteJsAt(webcontents_id_, kEditButtonQuery, kClickFn));
+  }
+
+  auto AddCustomCalendarShortcut(ui::Accelerator new_accel) {
+    CHECK(webcontents_id_);
+    return Steps(
+        ExecuteJsAt(webcontents_id_, kAddShortcutButtonQuery, kClickFn),
+        InAnyContext(SendAccelerator(webcontents_id_, new_accel)),
+        ExecuteJsAt(webcontents_id_, kDoneButtonQuery, kClickFn));
+  }
+
+  auto EditDefaultShortcut(ui::Accelerator new_accel) {
+    CHECK(webcontents_id_);
+    return Steps(
+        ExecuteJsAt(webcontents_id_, kAddShortcutButtonQuery, kClickFn),
+        InAnyContext(SendAccelerator(webcontents_id_, new_accel)),
+        ExecuteJsAt(webcontents_id_, kDoneButtonQuery, kClickFn));
+  }
+
+  auto ResetCalendarShortcuts() {
+    CHECK(webcontents_id_);
+    return Steps(
+        ExecuteJsAt(webcontents_id_, kCalendarAcceleratorRowQuery, kFocusFn),
+        ExecuteJsAt(webcontents_id_, kEditButtonQuery, kClickFn),
+        ExecuteJsAt(webcontents_id_, kRestoreDefaultsButtonQuery, kClickFn),
+        ExecuteJsAt(webcontents_id_, kDoneButtonQuery, kClickFn));
+  }
+
+  ui::InteractionSequence::StepBuilder LaunchShortcutCustomizationApp();
+
+  // Ensure focusing web contents doesn't accidentally block accelerator
+  // processing. When adding new accelerators, this method is called to
+  // prevent the system from processing Ash accelerators.
+  ui::InteractionSequence::StepBuilder EnsureAcceleratorsAreProcessed();
+
+  void SetUpOnMainThread() override;
+
+ protected:
+  base::test::ScopedFeatureList feature_list_;
+  ui::ElementIdentifier webcontents_id_;
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_UI_WEBUI_ASH_SHORTCUT_CUSTOMIZATION_SHORTCUT_CUSTOMIZATION_TEST_BASE_H_
diff --git a/chrome/browser/ui/webui/downloads/downloads_ui.cc b/chrome/browser/ui/webui/downloads/downloads_ui.cc
index a46a69f..96ff3244 100644
--- a/chrome/browser/ui/webui/downloads/downloads_ui.cc
+++ b/chrome/browser/ui/webui/downloads/downloads_ui.cc
@@ -110,8 +110,9 @@
       {"asyncScanningDownloadDesc", IDS_BLOCK_REASON_DEEP_SCANNING_UPDATED},
       {"asyncScanningDownloadDescSecond",
        IDS_BLOCK_REASON_DEEP_SCANNING_SECOND_UPDATED},
-      // TODO(crbug/1491184): Update this string for local decryption scans.
       {"promptForScanningDesc", IDS_BLOCK_REASON_PROMPT_FOR_SCANNING_UPDATED},
+      {"promptForLocalPasswordScanningDesc",
+       IDS_BLOCK_REASON_PROMPT_FOR_LOCAL_PASSWORD_SCANNING},
       {"controlDeepScan", IDS_DOWNLOAD_DEEP_SCAN_UPDATED},
       {"controlBypassDeepScan", IDS_DOWNLOAD_BYPASS_DEEP_SCAN_UPDATED},
       {"controlLocalPasswordScan", IDS_DOWNLOAD_LOCAL_PASSWORD_SCAN},
diff --git a/chrome/browser/ui/webui/help/version_updater_mac.mm b/chrome/browser/ui/webui/help/version_updater_mac.mm
index 67b1bdc7..6e1aeeb 100644
--- a/chrome/browser/ui/webui/help/version_updater_mac.mm
+++ b/chrome/browser/ui/webui/help/version_updater_mac.mm
@@ -31,6 +31,7 @@
 #include "chrome/browser/obsolete_system/obsolete_system.h"
 #include "chrome/browser/updater/browser_updater_client.h"
 #include "chrome/browser/updater/browser_updater_client_util.h"
+#include "chrome/browser/upgrade_detector/upgrade_detector.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/branded_strings.h"
 #include "chrome/grit/generated_resources.h"
@@ -357,7 +358,9 @@
       status = VersionUpdater::Status::NEARLY_UPDATED;
       break;
     case updater::UpdateService::UpdateState::State::kNoUpdate:
-      status = VersionUpdater::Status::UPDATED;
+      status = UpgradeDetector::GetInstance()->is_upgrade_available()
+                   ? VersionUpdater::Status::NEARLY_UPDATED
+                   : VersionUpdater::Status::UPDATED;
       break;
     case updater::UpdateService::UpdateState::State::kUpdateError:
       status = VersionUpdater::Status::FAILED;
diff --git a/chrome/browser/ui/webui/on_device_internals/BUILD.gn b/chrome/browser/ui/webui/on_device_internals/BUILD.gn
index 53ea88a..7a63eeb 100644
--- a/chrome/browser/ui/webui/on_device_internals/BUILD.gn
+++ b/chrome/browser/ui/webui/on_device_internals/BUILD.gn
@@ -11,5 +11,4 @@
     "//services/on_device_model/public/mojom",
   ]
   webui_module_path = "/"
-  use_typescript_sources = true
 }
diff --git a/chrome/browser/ui/webui/on_device_internals/on_device_internals_page.mojom b/chrome/browser/ui/webui/on_device_internals/on_device_internals_page.mojom
index f09d744..a83ed897 100644
--- a/chrome/browser/ui/webui/on_device_internals/on_device_internals_page.mojom
+++ b/chrome/browser/ui/webui/on_device_internals/on_device_internals_page.mojom
@@ -11,8 +11,9 @@
 interface OnDeviceInternalsPage {
   // Binds a new OnDeviceModel interface if possible using model assets loaded
   // from within `model_path`.
-  LoadModel(mojo_base.mojom.FilePath model_path) =>
-      (on_device_model.mojom.LoadModelResult result);
+  LoadModel(mojo_base.mojom.FilePath model_path,
+            pending_receiver<on_device_model.mojom.OnDeviceModel> model) =>
+      (string? error);
 
   // Returns the performance class based on benchmarks run on the device.
   GetEstimatedPerformanceClass() =>
diff --git a/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc b/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc
index 65fa803..a79f03c6 100644
--- a/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc
+++ b/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc
@@ -36,15 +36,18 @@
   page_receivers_.Add(this, std::move(receiver));
 }
 
-void OnDeviceInternalsUI::LoadModel(const base::FilePath& model_path,
-                                    LoadModelCallback callback) {
+void OnDeviceInternalsUI::LoadModel(
+    const base::FilePath& model_path,
+    mojo::PendingReceiver<on_device_model::mojom::OnDeviceModel> model,
+    LoadModelCallback callback) {
   // Warm the service while assets load in the background.
   std::ignore = GetService();
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::MayBlock()},
       base::BindOnce(&on_device_model::LoadModelAssets, model_path),
       base::BindOnce(&OnDeviceInternalsUI::OnModelAssetsLoaded,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+                     weak_ptr_factory_.GetWeakPtr(), std::move(model),
+                     std::move(callback)));
 }
 
 on_device_model::mojom::OnDeviceModelService&
@@ -66,7 +69,9 @@
 }
 
 void OnDeviceInternalsUI::OnModelAssetsLoaded(
+    mojo::PendingReceiver<on_device_model::mojom::OnDeviceModel> model,
     LoadModelCallback callback,
     on_device_model::ModelAssets assets) {
-  GetService().LoadModel(std::move(assets), std::move(callback));
+  GetService().LoadModel(std::move(assets), std::move(model),
+                         std::move(callback));
 }
diff --git a/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.h b/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.h
index 1f65350..dde3fc3e 100644
--- a/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.h
+++ b/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.h
@@ -29,12 +29,16 @@
   WEB_UI_CONTROLLER_TYPE_DECL();
 
   on_device_model::mojom::OnDeviceModelService& GetService();
-  void OnModelAssetsLoaded(LoadModelCallback callback,
-                           on_device_model::ModelAssets assets);
+  void OnModelAssetsLoaded(
+      mojo::PendingReceiver<on_device_model::mojom::OnDeviceModel> model,
+      LoadModelCallback callback,
+      on_device_model::ModelAssets assets);
 
   // mojom::OnDeviceInternalsPage:
-  void LoadModel(const base::FilePath& model_path,
-                 LoadModelCallback callback) override;
+  void LoadModel(
+      const base::FilePath& model_path,
+      mojo::PendingReceiver<on_device_model::mojom::OnDeviceModel> model,
+      LoadModelCallback callback) override;
   void GetEstimatedPerformanceClass(
       GetEstimatedPerformanceClassCallback callback) override;
 
diff --git a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
index 161d59e..a50ba5f 100644
--- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
@@ -94,10 +94,12 @@
 
 gfx::Size GetDefaultPdfMediaSizeMicrons() {
   PrintingContextDelegate delegate;
-  // The `PrintingContext` for "Save as PDF" does need to make system printing
-  // calls.
-  auto printing_context(
-      PrintingContext::Create(&delegate, /*skip_system_calls=*/false));
+  // The `PrintingContext` for "Save as PDF" does not need to make system
+  // printing calls, it just relies on localization plus hardcoded defaults
+  // from `PrintingContext::UsePdfSettings()`.  This means that OOP support
+  // is unnecessary in this case.
+  auto printing_context(PrintingContext::Create(
+      &delegate, PrintingContext::ProcessBehavior::kOopDisabled));
   printing_context->UsePdfSettings();
   gfx::Size pdf_media_size = printing_context->GetPdfPaperSizeDeviceUnits();
   float device_microns_per_device_unit =
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc
index 3648d83..aea43c7 100644
--- a/chrome/browser/ui/webui/settings/about_handler.cc
+++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -394,7 +394,7 @@
   policy_registrar_->Observe(
       policy::key::kDeviceAutoUpdateDisabled,
       base::BindRepeating(&AboutHandler::OnDeviceAutoUpdatePolicyChanged,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
@@ -402,6 +402,7 @@
   apply_changes_from_upgrade_observer_ = false;
   version_updater_.reset();
   policy_registrar_.reset();
+  weak_factory_.InvalidateWeakPtrs();
 }
 
 void AboutHandler::OnUpgradeRecommended() {
@@ -446,7 +447,7 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   static_cast<VersionUpdaterCros*>(version_updater_.get())
       ->GetUpdateStatus(base::BindRepeating(&AboutHandler::SetUpdateStatus,
-                                            base::Unretained(this)));
+                                            weak_factory_.GetWeakPtr()));
 #else
   RequestUpdate();
 #endif
@@ -528,7 +529,7 @@
     // Check for update after switching release channel.
     version_updater_->CheckForUpdate(
         base::BindRepeating(&AboutHandler::SetUpdateStatus,
-                            base::Unretained(this)),
+                            weak_factory_.GetWeakPtr()),
         VersionUpdater::PromoteCallback());
   }
 }
@@ -641,7 +642,7 @@
                                              int64_t update_size) {
   version_updater_->SetUpdateOverCellularOneTimePermission(
       base::BindRepeating(&AboutHandler::SetUpdateStatus,
-                          base::Unretained(this)),
+                          weak_factory_.GetWeakPtr()),
       update_version, update_size);
 }
 
@@ -777,10 +778,10 @@
 void AboutHandler::RequestUpdate() {
   version_updater_->CheckForUpdate(
       base::BindRepeating(&AboutHandler::SetUpdateStatus,
-                          base::Unretained(this)),
+                          weak_factory_.GetWeakPtr()),
 #if BUILDFLAG(IS_MAC)
       base::BindRepeating(&AboutHandler::SetPromotionState,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
 #else
       VersionUpdater::PromoteCallback());
 #endif  // BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 94c634a..46ae289 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -214,9 +214,7 @@
 #endif
     {"remove", IDS_REMOVE},
     {"restart", IDS_SETTINGS_RESTART},
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
     {"restartToApplyChanges", IDS_SETTINGS_RESTART_TO_APPLY_CHANGES},
-#endif
     {"retry", IDS_SETTINGS_RETRY},
     {"save", IDS_SAVE},
     {"searchResultBubbleText", IDS_SEARCH_RESULT_BUBBLE_TEXT},
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc
index 3bf10e1..b613a97 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -19,6 +19,8 @@
 #include "chrome/browser/commerce/shopping_service_factory.h"
 #include "chrome/browser/companion/core/features.h"
 #include "chrome/browser/download/bubble/download_bubble_prefs.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
 #include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h"
 #include "chrome/browser/performance_manager/public/user_tuning/user_tuning_utils.h"
 #include "chrome/browser/preloading/preloading_features.h"
@@ -554,6 +556,40 @@
       base::FeatureList::IsEnabled(
           blink::features::kMediaSessionEnterPictureInPicture));
 
+  // AI
+  optimization_guide::proto::ModelExecutionFeature
+      optimization_guide_features[3] = {
+          optimization_guide::proto::ModelExecutionFeature::
+              MODEL_EXECUTION_FEATURE_COMPOSE,
+          optimization_guide::proto::ModelExecutionFeature::
+              MODEL_EXECUTION_FEATURE_TAB_ORGANIZATION,
+          optimization_guide::proto::ModelExecutionFeature::
+              MODEL_EXECUTION_FEATURE_WALLPAPER_SEARCH,
+      };
+
+  auto* optimization_guide_service =
+      OptimizationGuideKeyedServiceFactory::GetForProfile(profile);
+  bool optimization_guide_feature_visible[4] = {false, false, false, false};
+
+  for (size_t i = 0; i < 3; i++) {
+    const bool& visible = optimization_guide_service->IsSettingVisible(
+        optimization_guide_features[i]);
+    optimization_guide_feature_visible[i + 1] = visible;
+
+    // The main toggle is visible only if at least one of the sub toggles is
+    // visible.
+    optimization_guide_feature_visible[0] |= visible;
+  }
+
+  html_source->AddBoolean("showAdvancedFeaturesMainControl",
+                          optimization_guide_feature_visible[0]);
+  html_source->AddBoolean("showComposeControl",
+                          optimization_guide_feature_visible[1]);
+  html_source->AddBoolean("showTabOrganizationControl",
+                          optimization_guide_feature_visible[2]);
+  html_source->AddBoolean("showWallpaperSearchControl",
+                          optimization_guide_feature_visible[3]);
+
   TryShowHatsSurveyWithTimeout();
 }
 
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/browser/ui/webui/settings/site_settings_helper.cc
index d657bff..128c372 100644
--- a/chrome/browser/ui/webui/settings/site_settings_helper.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_helper.cc
@@ -177,7 +177,8 @@
     {ContentSettingsType::HTTP_ALLOWED, nullptr},
     {ContentSettingsType::HTTPS_ENFORCED, nullptr},
     {ContentSettingsType::FORMFILL_METADATA, nullptr},
-    {ContentSettingsType::FEDERATED_IDENTITY_ACTIVE_SESSION, nullptr},
+    {ContentSettingsType::DEPRECATED_FEDERATED_IDENTITY_ACTIVE_SESSION,
+     nullptr},
     {ContentSettingsType::AUTO_DARK_WEB_CONTENT, nullptr},
     {ContentSettingsType::REQUEST_DESKTOP_SITE, nullptr},
     {ContentSettingsType::NOTIFICATION_INTERACTIONS, nullptr},
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 515b8cc..10d19c4 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
@@ -118,6 +118,11 @@
       {"genericErrorDescription",
        IDS_NTP_WALLPAPER_SEARCH_GENERIC_ERROR_DESCRIPTION},
       {"genericErrorTitle", IDS_NTP_WALLPAPER_SEARCH_GENERIC_ERROR_TITLE},
+      {"requestThrottledDescription",
+       IDS_NTP_WALLPAPER_SEARCH_REQUEST_THROTTLED_DESCRIPTION},
+      {"requestThrottledTitle",
+       IDS_NTP_WALLPAPER_SEARCH_REQUEST_THROTTLED_TITLE},
+      {"tryAgain", IDS_NTP_WALLPAPER_SEARCH_TRY_AGAIN_CTA},
       {"wallpaperSearchHeader", IDS_NTP_WALLPAPER_SEARCH_HEADER},
       {"wallpaperSearchHistoryHeader", IDS_NTP_WALLPAPER_SEARCH_HISTORY_HEADER},
       {"wallpaperSearchSubmitBtn", IDS_NTP_WALLPAPER_SEARCH_SUBMIT_BTN_TEXT},
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search.mojom b/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search.mojom
index 84acecb..9583591 100644
--- a/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search.mojom
+++ b/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search.mojom
@@ -37,6 +37,8 @@
   kOk,
   // Generic error, not specified.
   kError,
+  // Too many requests.
+  kRequestThrottled,
 };
 
 // Browser-side handler for requests from WebUI page.
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_handler.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_handler.cc
index 70eacf6..c626bc5 100644
--- a/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_handler.cc
+++ b/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_handler.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/ui/webui/cr_components/theme_color_picker/customize_chrome_colors.h"
 #include "chrome/common/webui_url_constants.h"
 #include "components/image_fetcher/core/image_decoder.h"
+#include "components/optimization_guide/core/model_execution/optimization_guide_model_execution_error.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/optimization_guide_util.h"
 #include "components/optimization_guide/proto/features/wallpaper_search.pb.h"
@@ -292,6 +293,15 @@
     optimization_guide::OptimizationGuideModelExecutionResult result,
     std::unique_ptr<optimization_guide::ModelQualityLogEntry> log_entry) {
   if (!result.has_value()) {
+    if (result.error().error() ==
+        optimization_guide::OptimizationGuideModelExecutionError::
+            ModelExecutionError::kRequestThrottled) {
+      std::move(callback).Run(
+          side_panel::customize_chrome::mojom::WallpaperSearchStatus::
+              kRequestThrottled,
+          std::vector<
+              side_panel::customize_chrome::mojom::WallpaperSearchResultPtr>());
+    }
     return;
   }
   auto response = optimization_guide::ParsedAnyMetadata<
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_handler_unittest.cc
index 16d6db0..aae9097 100644
--- a/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_handler_unittest.cc
+++ b/chrome/browser/ui/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_handler_unittest.cc
@@ -593,6 +593,53 @@
   EXPECT_EQ(static_cast<int>(images.size()), response.images_size());
 }
 
+TEST_F(WallpaperSearchHandlerTest, GetWallpaperSearchResults_RequestThrottled) {
+  optimization_guide::proto::WallpaperSearchRequest request;
+  optimization_guide::OptimizationGuideModelExecutionResultCallback
+      done_callback;
+  base::OnceCallback<void(const gfx::Image&)> decoder_callback1;
+  base::OnceCallback<void(const gfx::Image&)> decoder_callback2;
+  EXPECT_CALL(mock_optimization_guide_keyed_service(), ExecuteModel(_, _, _))
+      .WillOnce(Invoke(
+          [&request, &done_callback](
+              optimization_guide::proto::ModelExecutionFeature feature_arg,
+              const google::protobuf::MessageLite& request_arg,
+              optimization_guide::OptimizationGuideModelExecutionResultCallback
+                  done_callback_arg) {
+            ASSERT_EQ(request.GetTypeName(), request_arg.GetTypeName());
+            request.CheckTypeAndMergeFrom(request_arg);
+            done_callback = std::move(done_callback_arg);
+          }));
+  base::MockCallback<WallpaperSearchHandler::GetWallpaperSearchResultsCallback>
+      callback;
+
+  handler().GetWallpaperSearchResults("foo", absl::nullopt, absl::nullopt,
+                                      nullptr, callback.Get());
+  EXPECT_EQ("foo", request.descriptors().descriptor_a());
+  EXPECT_TRUE(request.descriptors().descriptor_b().empty());
+  EXPECT_TRUE(request.descriptors().descriptor_c().empty());
+  EXPECT_TRUE(request.descriptors().descriptor_d().empty());
+
+  std::vector<side_panel::customize_chrome::mojom::WallpaperSearchResultPtr>
+      images;
+  side_panel::customize_chrome::mojom::WallpaperSearchStatus status;
+  EXPECT_CALL(callback, Run(_, _))
+      .WillOnce(DoAll(SaveArg<0>(&status), MoveArg<1>(&images)));
+
+  std::move(done_callback)
+      .Run(
+          base::unexpected(
+              optimization_guide::OptimizationGuideModelExecutionError::
+                  FromModelExecutionError(
+                      optimization_guide::OptimizationGuideModelExecutionError::
+                          ModelExecutionError::kRequestThrottled)),
+          nullptr);
+
+  EXPECT_EQ(status, side_panel::customize_chrome::mojom::WallpaperSearchStatus::
+                        kRequestThrottled);
+  EXPECT_EQ(images.size(), 0u);
+}
+
 TEST_F(WallpaperSearchHandlerTest, SetBackgroundToWallpaperSearchResult) {
   // Fill wallpaper_search_results_ with 2 bitmaps.
   optimization_guide::proto::WallpaperSearchRequest request;
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
index 4b7ebbd..7b265f9a 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
@@ -780,7 +780,8 @@
     case TabOrganizationRequest::State::COMPLETED: {
       if (session.tab_organizations().size() > 0) {
         mojo_session->state = tab_search::mojom::TabOrganizationState::kSuccess;
-        for (const auto& organization : session.tab_organizations()) {
+        for (const std::unique_ptr<TabOrganization>& organization :
+             session.tab_organizations()) {
           organizations.emplace_back(
               GetMojoForTabOrganization(organization.get()));
         }
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index c855875..e67c26f4 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -431,6 +431,7 @@
     "//chrome/browser/favicon",
     "//chrome/browser/profiles:profile",
     "//chrome/common",
+    "//chrome/common:chrome_features",
     "//chrome/common:non_code_constants",
     "//components/base32:base32",
     "//components/browsing_data/content",
@@ -799,10 +800,12 @@
     "//chrome/browser",
     "//chrome/browser:browser_process",
     "//chrome/browser/apps/app_service",
+    "//chrome/browser/apps/link_capturing:test_support",
     "//chrome/browser/extensions:test_support",
     "//chrome/browser/profiles:profile",
     "//chrome/browser/web_applications/extensions:extensions",
     "//chrome/common",
+    "//chrome/common:chrome_features",
     "//chrome/test:test_support",
     "//components/os_crypt/sync:test_support",
     "//components/services/app_service",
@@ -939,6 +942,7 @@
     "//chrome/browser/browsing_data:constants",
     "//chrome/browser/devtools:test_support",
     "//chrome/browser/profiles:profile",
+    "//chrome/common:chrome_features",
     "//chrome/test:test_support",
     "//chrome/test:test_support_ui",
     "//components/browsing_data/core",
@@ -1004,6 +1008,7 @@
     "//base",
     "//chrome/browser/apps/app_service",
     "//chrome/browser/apps/app_service:app_registry_cache_waiter",
+    "//chrome/browser/apps/link_capturing:test_support",
     "//chrome/test:test_support",
     "//chrome/test:test_support_ui",
     "//components/webapps/browser",
diff --git a/chrome/browser/web_applications/jobs/link_capturing.cc b/chrome/browser/web_applications/jobs/link_capturing.cc
index 0f695f2..6926032 100644
--- a/chrome/browser/web_applications/jobs/link_capturing.cc
+++ b/chrome/browser/web_applications/jobs/link_capturing.cc
@@ -6,6 +6,7 @@
 
 #include "base/values.h"
 #include "chrome/browser/web_applications/locks/all_apps_lock.h"
+#include "chrome/browser/web_applications/proto/web_app_proto_package.pb.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
@@ -21,48 +22,76 @@
   debug_value.Set("app_id", app_id);
   debug_value.Set("set_to_preferred", set_to_preferred);
 
-  bool is_already_preferred = lock.registrar().CapturesLinksInScope(app_id);
-
-  // Only update in web_app DB if the user selected choice does not match the
-  // one in the DB currently.
-  bool requires_update = (set_to_preferred && !is_already_preferred) ||
-                         (!set_to_preferred && is_already_preferred);
-
-  debug_value.Set("requires_update", requires_update);
-  if (!requires_update) {
+  if (!lock.registrar().IsLocallyInstalled(app_id)) {
+    debug_value.Set("result", "App not installed.");
+    return base::Value(std::move(debug_value));
+  }
+  if (lock.registrar().IsShortcutApp(app_id)) {
+    debug_value.Set("result", "App is created as a shortcut.");
     return base::Value(std::move(debug_value));
   }
 
-  // TODO(b/273830801): Automatically call observers when changes are committed
-  // to the web_app DB.
-  for (const webapps::AppId& id : lock.registrar().GetAppIds()) {
-    if (id == app_id) {
+  // When disabling, simply disable & exit because this doesn't need to affect
+  // the state of other apps.
+  if (!set_to_preferred) {
+    {
+      ScopedRegistryUpdate update = lock.sync_bridge().BeginUpdate();
+      WebApp* app_to_update = update->UpdateApp(app_id);
+      app_to_update->SetLinkCapturingUserPreference(
+          proto::LinkCapturingUserPreference::DO_NOT_CAPTURE_SUPPORTED_LINKS);
+    }
+    debug_value.Set("app_updated", true);
+    // TODO(b/273830801): Automatically call observers when changes are
+    // committed to the web_app DB (here and below).
+    lock.registrar().NotifyWebAppUserLinkCapturingPreferencesChanged(
+        app_id, set_to_preferred);
+    return base::Value(std::move(debug_value));
+  }
+
+  // Whe enabling, any app with the same scope (overlapping) that is explicitly
+  // enabled must be disabled to prevent multiple apps from capturing links on
+  // the same scope.
+  for (const webapps::AppId& other_app_id : lock.registrar().GetAppIds()) {
+    if (other_app_id == app_id) {
       {
         ScopedRegistryUpdate update = lock.sync_bridge().BeginUpdate();
         WebApp* app_to_update = update->UpdateApp(app_id);
-        app_to_update->SetIsUserSelectedAppForSupportedLinks(set_to_preferred);
+        app_to_update->SetLinkCapturingUserPreference(
+            set_to_preferred
+                ? proto::LinkCapturingUserPreference::CAPTURE_SUPPORTED_LINKS
+                : proto::LinkCapturingUserPreference::
+                      DO_NOT_CAPTURE_SUPPORTED_LINKS);
       }
       debug_value.Set("app_updated", true);
       lock.registrar().NotifyWebAppUserLinkCapturingPreferencesChanged(
           app_id, set_to_preferred);
-    } else {
-      // For all other app_ids, if one is already set as the preferred, reset
-      // all other apps in the registry if they were previously set to be a
-      // preferred app to capture similar type of links according to scope
-      // prefixes.
-      if (set_to_preferred && lock.registrar().CapturesLinksInScope(id) &&
-          lock.registrar().AppScopesMatchForUserLinkCapturing(app_id, id)) {
-        {
-          ScopedRegistryUpdate update = lock.sync_bridge().BeginUpdate();
-          WebApp* app_to_update = update->UpdateApp(id);
-          app_to_update->SetIsUserSelectedAppForSupportedLinks(
-              /*is_user_selected_app_for_capturing_links=*/false);
-        }
-        debug_value.EnsureList("capturing_apps_disabled")->Append(id);
-        lock.registrar().NotifyWebAppUserLinkCapturingPreferencesChanged(
-            id, /*is_preferred=*/false);
-      }
+      continue;
     }
+    if (!lock.registrar().CanCaptureLinksInScope(other_app_id)) {
+      continue;
+    }
+    if (!lock.registrar().AppScopesMatchForUserLinkCapturing(app_id,
+                                                             other_app_id)) {
+      continue;
+    }
+    const WebApp* other_app = lock.registrar().GetAppById(other_app_id);
+    CHECK(other_app);
+    // Only update apps that are explicitly turned on. We want to leave any set
+    // as 'default' to stay as such, allowing them to take over if this one is
+    // uninstalled.
+    if (other_app->user_link_capturing_preference() !=
+        proto::LinkCapturingUserPreference::CAPTURE_SUPPORTED_LINKS) {
+      continue;
+    }
+    {
+      ScopedRegistryUpdate update = lock.sync_bridge().BeginUpdate();
+      WebApp* app_to_update = update->UpdateApp(other_app_id);
+      app_to_update->SetLinkCapturingUserPreference(
+          proto::LinkCapturingUserPreference::DO_NOT_CAPTURE_SUPPORTED_LINKS);
+    }
+    debug_value.EnsureList("capturing_apps_disabled")->Append(other_app_id);
+    lock.registrar().NotifyWebAppUserLinkCapturingPreferencesChanged(
+        other_app_id, /*is_preferred=*/false);
   }
   return base::Value(std::move(debug_value));
 }
diff --git a/chrome/browser/web_applications/jobs/link_capturing_unittest.cc b/chrome/browser/web_applications/jobs/link_capturing_unittest.cc
index f694838..ab789e6 100644
--- a/chrome/browser/web_applications/jobs/link_capturing_unittest.cc
+++ b/chrome/browser/web_applications/jobs/link_capturing_unittest.cc
@@ -2,8 +2,6 @@
 // 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/jobs/link_capturing.h"
-
 #include "base/test/test_future.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/test/web_app_test.h"
@@ -11,6 +9,7 @@
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
+#include "chrome/common/chrome_features.h"
 #include "components/webapps/common/web_app_id.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -18,39 +17,60 @@
 namespace web_app {
 namespace {
 
-class LinkCapturingJobTest : public WebAppTest {
+class LinkCapturingJobTest : public WebAppTest,
+                             public testing::WithParamInterface<bool> {
  public:
   const GURL kTestAppUrl = GURL("https://example.com/index.html");
   const GURL kTestOverlappingAppUrl = GURL("https://example.com/index2.html");
   const GURL kTestAppCapturablePage = GURL("https://example.com/page.html");
 
-  LinkCapturingJobTest() = default;
+  LinkCapturingJobTest() {
+    feature_list_.InitAndEnableFeatureWithParameters(
+        features::kDesktopPWAsLinkCapturing,
+        {{features::kLinksCapturedByDefault.name,
+          (GetParam() ? "true" : "false")}});
+  }
   ~LinkCapturingJobTest() override = default;
 
+  bool LinkCapturingEnabledByDefault() const { return GetParam(); }
+
   void SetUp() override {
     WebAppTest::SetUp();
     test::AwaitStartWebAppProviderAndSubsystems(profile());
   }
 
   WebAppProvider* provider() { return WebAppProvider::GetForTest(profile()); }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
 };
 
-TEST_F(LinkCapturingJobTest, SingleAppEnabled) {
+TEST_P(LinkCapturingJobTest, SingleAppEnabled) {
   webapps::AppId app_id = test::InstallWebApp(
       profile(), WebAppInstallInfo::CreateWithStartUrlForTesting(kTestAppUrl));
 
+  // For LinkCapturingEnabledByDefault(), simply test the default & that
+  // enabling it doesn't change anything.
   EXPECT_TRUE(provider()->registrar_unsafe().IsLinkCapturableByApp(
       app_id, kTestAppCapturablePage));
-  EXPECT_FALSE(provider()->registrar_unsafe().CapturesLinksInScope(app_id));
-  EXPECT_EQ(absl::nullopt,
-            provider()->registrar_unsafe().FindAppThatCapturesLinksInScope(
-                kTestAppCapturablePage));
+  EXPECT_EQ(LinkCapturingEnabledByDefault(),
+            provider()->registrar_unsafe().CapturesLinksInScope(app_id));
+  EXPECT_EQ(
+      LinkCapturingEnabledByDefault() ? absl::optional(app_id) : absl::nullopt,
+      provider()->registrar_unsafe().FindAppThatCapturesLinksInScope(
+          kTestAppCapturablePage));
 
   base::test::TestFuture<void> preference_set;
   provider()->scheduler().SetAppCapturesSupportedLinksDisableOverlapping(
-      app_id, true, preference_set.GetCallback());
+      app_id, /*set_to_preferred=*/true, preference_set.GetCallback());
   ASSERT_TRUE(preference_set.Wait());
 
+  EXPECT_EQ(provider()
+                ->registrar_unsafe()
+                .GetAppById(app_id)
+                ->user_link_capturing_preference(),
+            proto::LinkCapturingUserPreference::CAPTURE_SUPPORTED_LINKS);
+
   EXPECT_TRUE(provider()->registrar_unsafe().IsLinkCapturableByApp(
       app_id, kTestAppCapturablePage));
   EXPECT_TRUE(provider()->registrar_unsafe().CapturesLinksInScope(app_id));
@@ -59,7 +79,29 @@
                 kTestAppCapturablePage));
 }
 
-TEST_F(LinkCapturingJobTest, DisablesOtherApps) {
+TEST_P(LinkCapturingJobTest, SingleAppDisabled) {
+  webapps::AppId app_id = test::InstallWebApp(
+      profile(), WebAppInstallInfo::CreateWithStartUrlForTesting(kTestAppUrl));
+
+  base::test::TestFuture<void> preference_set;
+  provider()->scheduler().SetAppCapturesSupportedLinksDisableOverlapping(
+      app_id, /*set_to_preferred=*/false, preference_set.GetCallback());
+  ASSERT_TRUE(preference_set.Wait());
+
+  EXPECT_EQ(provider()
+                ->registrar_unsafe()
+                .GetAppById(app_id)
+                ->user_link_capturing_preference(),
+            proto::LinkCapturingUserPreference::DO_NOT_CAPTURE_SUPPORTED_LINKS);
+  EXPECT_TRUE(provider()->registrar_unsafe().IsLinkCapturableByApp(
+      app_id, kTestAppCapturablePage));
+  EXPECT_FALSE(provider()->registrar_unsafe().CapturesLinksInScope(app_id));
+  EXPECT_EQ(absl::nullopt,
+            provider()->registrar_unsafe().FindAppThatCapturesLinksInScope(
+                kTestAppCapturablePage));
+}
+
+TEST_P(LinkCapturingJobTest, DisablesOtherApps) {
   webapps::AppId app1_id = test::InstallWebApp(
       profile(), WebAppInstallInfo::CreateWithStartUrlForTesting(kTestAppUrl));
   webapps::AppId app2_id = test::InstallWebApp(
@@ -69,7 +111,7 @@
   {
     base::test::TestFuture<void> preference_set;
     provider()->scheduler().SetAppCapturesSupportedLinksDisableOverlapping(
-        app1_id, true, preference_set.GetCallback());
+        app1_id, /*set_to_preferred=*/true, preference_set.GetCallback());
     ASSERT_TRUE(preference_set.Wait());
   }
 
@@ -80,7 +122,7 @@
   {
     base::test::TestFuture<void> preference_set;
     provider()->scheduler().SetAppCapturesSupportedLinksDisableOverlapping(
-        app2_id, true, preference_set.GetCallback());
+        app2_id, /*set_to_preferred=*/true, preference_set.GetCallback());
     ASSERT_TRUE(preference_set.Wait());
   }
 
@@ -94,5 +136,75 @@
                 kTestAppCapturablePage));
 }
 
+TEST_P(LinkCapturingJobTest, DefaultOnChoosesFirstApp) {
+  if (!LinkCapturingEnabledByDefault()) {
+    GTEST_SKIP();
+  }
+  webapps::AppId app1_id = test::InstallWebApp(
+      profile(), WebAppInstallInfo::CreateWithStartUrlForTesting(kTestAppUrl));
+  webapps::AppId app2_id = test::InstallWebApp(
+      profile(),
+      WebAppInstallInfo::CreateWithStartUrlForTesting(kTestOverlappingAppUrl));
+
+  EXPECT_TRUE(provider()->registrar_unsafe().CapturesLinksInScope(app1_id));
+  EXPECT_FALSE(provider()->registrar_unsafe().CapturesLinksInScope(app2_id));
+}
+
+TEST_P(LinkCapturingJobTest, ExplicitDisablingOverrideDefaultBehavior) {
+  webapps::AppId app1_id = test::InstallWebApp(
+      profile(), WebAppInstallInfo::CreateWithStartUrlForTesting(kTestAppUrl));
+  webapps::AppId app2_id = test::InstallWebApp(
+      profile(),
+      WebAppInstallInfo::CreateWithStartUrlForTesting(kTestOverlappingAppUrl));
+
+  // Disabling the second should always cause it to be disabled, even in
+  // 'default on' scenario after the first app is uninstalled.
+  {
+    base::test::TestFuture<void> preference_set;
+    provider()->scheduler().SetAppCapturesSupportedLinksDisableOverlapping(
+        app2_id, /*set_to_preferred=*/false, preference_set.GetCallback());
+    ASSERT_TRUE(preference_set.Wait());
+  }
+
+  EXPECT_FALSE(provider()->registrar_unsafe().CapturesLinksInScope(app2_id));
+
+  test::UninstallWebApp(profile(), app1_id);
+
+  // The app remains disabled, if it we were "default on".
+  EXPECT_FALSE(provider()->registrar_unsafe().CapturesLinksInScope(app2_id));
+}
+
+TEST_P(LinkCapturingJobTest, UninstallOverlappingRevertsToDefault) {
+  webapps::AppId app1_id = test::InstallWebApp(
+      profile(), WebAppInstallInfo::CreateWithStartUrlForTesting(kTestAppUrl));
+  webapps::AppId app2_id = test::InstallWebApp(
+      profile(),
+      WebAppInstallInfo::CreateWithStartUrlForTesting(kTestOverlappingAppUrl));
+
+  // Enable the first, which should explicitly disable the second.
+  {
+    base::test::TestFuture<void> preference_set;
+    provider()->scheduler().SetAppCapturesSupportedLinksDisableOverlapping(
+        app1_id, /*set_to_preferred=*/true, preference_set.GetCallback());
+    ASSERT_TRUE(preference_set.Wait());
+  }
+
+  EXPECT_TRUE(provider()->registrar_unsafe().CapturesLinksInScope(app1_id));
+  EXPECT_FALSE(provider()->registrar_unsafe().CapturesLinksInScope(app2_id));
+
+  // Uninstalling the first should make the second app revert to the default.
+  test::UninstallWebApp(profile(), app1_id);
+
+  EXPECT_EQ(LinkCapturingEnabledByDefault(),
+            provider()->registrar_unsafe().CapturesLinksInScope(app2_id));
+}
+
+INSTANTIATE_TEST_SUITE_P(,
+                         LinkCapturingJobTest,
+                         testing::Values(true, false),
+                         [](const testing::TestParamInfo<bool>& info) {
+                           return info.param ? "DefaultOn" : "DefaultOff";
+                         });
+
 }  // namespace
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/mojom/BUILD.gn b/chrome/browser/web_applications/mojom/BUILD.gn
index de93336..e13d3c42 100644
--- a/chrome/browser/web_applications/mojom/BUILD.gn
+++ b/chrome/browser/web_applications/mojom/BUILD.gn
@@ -5,5 +5,4 @@
 
   public_deps = []
   webui_module_path = "/"
-  use_typescript_sources = true
 }
diff --git a/chrome/browser/web_applications/proto/BUILD.gn b/chrome/browser/web_applications/proto/BUILD.gn
index dcb3712..da1eca6 100644
--- a/chrome/browser/web_applications/proto/BUILD.gn
+++ b/chrome/browser/web_applications/proto/BUILD.gn
@@ -10,6 +10,7 @@
     "web_app.proto",
     "web_app_launch_handler.proto",
     "web_app_os_integration_state.proto",
+    "web_app_proto_package.proto",
     "web_app_share_target.proto",
     "web_app_tab_strip.proto",
     "web_app_translations.proto",
diff --git a/chrome/browser/web_applications/proto/web_app.proto b/chrome/browser/web_applications/proto/web_app.proto
index ce4e66f..f06b473 100644
--- a/chrome/browser/web_applications/proto/web_app.proto
+++ b/chrome/browser/web_applications/proto/web_app.proto
@@ -8,11 +8,14 @@
 import "chrome/browser/ash/system_web_apps/types/proto/system_web_app_data.proto";
 import "chrome/browser/web_applications/proto/web_app_launch_handler.proto";
 import "chrome/browser/web_applications/proto/web_app_os_integration_state.proto";
+import "chrome/browser/web_applications/proto/web_app_proto_package.proto";
 import "chrome/browser/web_applications/proto/web_app_share_target.proto";
 import "chrome/browser/web_applications/proto/web_app_tab_strip.proto";
 
 option optimize_for = LITE_RUNTIME;
 
+// TODO(http://b/307989065) Make this web_app.proto and remove "Proto" from type
+// names.
 package web_app;
 
 // A mapping between a MIME type and a set of file extensions for a file handler
@@ -466,7 +469,8 @@
 
   // Stores whether the current web app is set as the default app to capture
   // links.
-  optional bool is_user_selected_app_for_capturing_links = 63;
+  optional proto.LinkCapturingUserPreference user_link_capturing_preference =
+      63;
 
   // Time the app was updated as part of a full install. For example when a
   // policy installs an app that is already in the DB installed as a
diff --git a/chrome/browser/web_applications/proto/web_app_launch_handler.proto b/chrome/browser/web_applications/proto/web_app_launch_handler.proto
index de341598..0a76ec2d 100644
--- a/chrome/browser/web_applications/proto/web_app_launch_handler.proto
+++ b/chrome/browser/web_applications/proto/web_app_launch_handler.proto
@@ -6,6 +6,7 @@
 
 option optimize_for = LITE_RUNTIME;
 
+// TODO(http://b/307989065) Make this web_app.proto
 package web_app;
 
 // A proto representing the "launch_handler" manifest field.
diff --git a/chrome/browser/web_applications/proto/web_app_proto_package.proto b/chrome/browser/web_applications/proto/web_app_proto_package.proto
new file mode 100644
index 0000000..95c5920
--- /dev/null
+++ b/chrome/browser/web_applications/proto/web_app_proto_package.proto
@@ -0,0 +1,19 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package web_app.proto;
+
+// This file is separate from web_app.proto to specify the web_app.proto
+// package, which all proto types should eventually move to.
+// http://b/307989065
+
+enum LinkCapturingUserPreference {
+  LINK_CAPTURING_PREFERENCE_DEFAULT = 0;
+  CAPTURE_SUPPORTED_LINKS = 1;
+  DO_NOT_CAPTURE_SUPPORTED_LINKS = 2;
+}
diff --git a/chrome/browser/web_applications/proto/web_app_share_target.proto b/chrome/browser/web_applications/proto/web_app_share_target.proto
index ec13a9b..4eef555 100644
--- a/chrome/browser/web_applications/proto/web_app_share_target.proto
+++ b/chrome/browser/web_applications/proto/web_app_share_target.proto
@@ -6,6 +6,7 @@
 
 option optimize_for = LITE_RUNTIME;
 
+// TODO(http://b/307989065) Make this web_app.proto
 package web_app;
 
 // A proto representing a ShareTargetParamsFile
diff --git a/chrome/browser/web_applications/proto/web_app_translations.proto b/chrome/browser/web_applications/proto/web_app_translations.proto
index 4455270..41422e7d 100644
--- a/chrome/browser/web_applications/proto/web_app_translations.proto
+++ b/chrome/browser/web_applications/proto/web_app_translations.proto
@@ -6,6 +6,7 @@
 
 option optimize_for = LITE_RUNTIME;
 
+// TODO(http://b/307989065) Make this web_app.proto
 package web_app;
 
 // Translations for all apps.
diff --git a/chrome/browser/web_applications/test/web_app_test_utils.cc b/chrome/browser/web_applications/test/web_app_test_utils.cc
index 5a3f7c4..b0c78110 100644
--- a/chrome/browser/web_applications/test/web_app_test_utils.cc
+++ b/chrome/browser/web_applications/test/web_app_test_utils.cc
@@ -42,6 +42,7 @@
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_location.h"
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
+#include "chrome/browser/web_applications/proto/web_app_proto_package.pb.h"
 #include "chrome/browser/web_applications/test/web_app_test_observers.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_chromeos_data.h"
@@ -933,7 +934,8 @@
     app->SetIsolationData(isolation_data);
   }
 
-  app->SetIsUserSelectedAppForSupportedLinks(random.next_bool());
+  app->SetLinkCapturingUserPreference(NEXT_PROTO_ENUM(
+      random, proto::LinkCapturingUserPreference, /*skip_zero=*/false));
 
   app->SetLatestInstallTime(random.next_time());
 
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc
index a3984c6..83c6ada 100644
--- a/chrome/browser/web_applications/web_app.cc
+++ b/chrome/browser/web_applications/web_app.cc
@@ -25,6 +25,7 @@
 #include "chrome/browser/web_applications/generated_icon_fix_util.h"
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom-shared.h"
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
+#include "chrome/browser/web_applications/proto/web_app_proto_package.pb.h"
 #include "chrome/browser/web_applications/web_app_chromeos_data.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
@@ -686,10 +687,9 @@
   isolation_data_ = isolation_data;
 }
 
-void WebApp::SetIsUserSelectedAppForSupportedLinks(
-    bool is_user_selected_app_for_capturing_links) {
-  is_user_selected_app_for_capturing_links_ =
-      is_user_selected_app_for_capturing_links;
+void WebApp::SetLinkCapturingUserPreference(
+    proto::LinkCapturingUserPreference user_link_capturing_preference) {
+  user_link_capturing_preference_ = user_link_capturing_preference;
 }
 
 void WebApp::SetSupportedLinksOfferIgnoreCount(int ignore_count) {
@@ -989,7 +989,7 @@
         app.always_show_toolbar_in_fullscreen_,
         app.current_os_integration_states_,
         app.isolation_data_,
-        app.is_user_selected_app_for_capturing_links_,
+        app.user_link_capturing_preference_,
         app.latest_install_time_,
         app.generated_icon_fix_,
         app.supported_links_offer_ignore_count_,
@@ -1204,8 +1204,8 @@
 
   root.Set("isolation_data", OptionalAsDebugValue(isolation_data_));
 
-  root.Set("is_user_selected_app_for_capturing_links",
-           is_user_selected_app_for_capturing_links_);
+  root.Set("user_link_capturing_preference",
+           base::ToString(user_link_capturing_preference_));
 
   root.Set("latest_install_time", base::ToString(latest_install_time_));
 
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h
index ac8abc7..05fc85a 100644
--- a/chrome/browser/web_applications/web_app.h
+++ b/chrome/browser/web_applications/web_app.h
@@ -21,6 +21,7 @@
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom-forward.h"
 #include "chrome/browser/web_applications/proto/web_app.pb.h"
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
+#include "chrome/browser/web_applications/proto/web_app_proto_package.pb.h"
 #include "chrome/browser/web_applications/scope_extension_info.h"
 #include "chrome/browser/web_applications/web_app_chromeos_data.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
@@ -409,8 +410,8 @@
     return isolation_data_;
   }
 
-  bool is_user_selected_app_for_capturing_links() const {
-    return is_user_selected_app_for_capturing_links_;
+  proto::LinkCapturingUserPreference user_link_capturing_preference() const {
+    return user_link_capturing_preference_;
   }
 
   const base::Time& latest_install_time() const { return latest_install_time_; }
@@ -516,8 +517,8 @@
   void SetCurrentOsIntegrationStates(
       proto::WebAppOsIntegrationState current_os_integration_states);
   void SetIsolationData(IsolationData isolation_data);
-  void SetIsUserSelectedAppForSupportedLinks(
-      bool is_user_selected_app_for_capturing_links);
+  void SetLinkCapturingUserPreference(
+      proto::LinkCapturingUserPreference user_link_capturing_preference);
   void SetSupportedLinksOfferIgnoreCount(int ignore_count);
   void SetSupportedLinksOfferDismissCount(int dismiss_count);
 
@@ -662,7 +663,8 @@
 
   absl::optional<IsolationData> isolation_data_;
 
-  bool is_user_selected_app_for_capturing_links_ = false;
+  proto::LinkCapturingUserPreference user_link_capturing_preference_ =
+      proto::LinkCapturingUserPreference::LINK_CAPTURING_PREFERENCE_DEFAULT;
 
   base::Time latest_install_time_;
 
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc
index 1d2071c0..f9445133 100644
--- a/chrome/browser/web_applications/web_app_database.cc
+++ b/chrome/browser/web_applications/web_app_database.cc
@@ -892,8 +892,8 @@
     }
   }
 
-  local_data->set_is_user_selected_app_for_capturing_links(
-      web_app.is_user_selected_app_for_capturing_links());
+  local_data->set_user_link_capturing_preference(
+      web_app.user_link_capturing_preference());
 
   if (!web_app.latest_install_time().is_null()) {
     local_data->set_latest_install_time(
@@ -1646,9 +1646,9 @@
         *location, version, controlled_frame_partitions, pending_update_info));
   }
 
-  if (local_data.has_is_user_selected_app_for_capturing_links()) {
-    web_app->SetIsUserSelectedAppForSupportedLinks(
-        local_data.is_user_selected_app_for_capturing_links());
+  if (local_data.has_user_link_capturing_preference()) {
+    web_app->SetLinkCapturingUserPreference(
+        local_data.user_link_capturing_preference());
   }
 
   if (local_data.has_latest_install_time()) {
diff --git a/chrome/browser/web_applications/web_app_registrar.cc b/chrome/browser/web_applications/web_app_registrar.cc
index 6b0ab32..54219060c 100644
--- a/chrome/browser/web_applications/web_app_registrar.cc
+++ b/chrome/browser/web_applications/web_app_registrar.cc
@@ -31,6 +31,7 @@
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
 #include "chrome/browser/web_applications/policy/web_app_policy_manager.h"
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
+#include "chrome/browser/web_applications/proto/web_app_proto_package.pb.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
@@ -41,6 +42,7 @@
 #include "chrome/browser/web_applications/web_app_translation_manager.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/common/chrome_features.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/isolated_web_apps_policy.h"
 #include "content/public/browser/storage_partition_config.h"
 #include "content/public/common/content_features.h"
@@ -996,14 +998,73 @@
       profile_, partition_name, true);
 }
 
-bool WebAppRegistrar::CapturesLinksInScope(const webapps::AppId& app_id) const {
+bool WebAppRegistrar::CanCaptureLinksInScope(
+    const webapps::AppId& app_id) const {
+  if (!base::FeatureList::IsEnabled(features::kDesktopPWAsLinkCapturing)) {
+    return false;
+  }
   if (!IsLocallyInstalled(app_id) || IsShortcutApp(app_id)) {
     return false;
   }
+  return true;
+}
+
+bool WebAppRegistrar::CapturesLinksInScope(const webapps::AppId& app_id) const {
+  if (!CanCaptureLinksInScope(app_id)) {
+    return false;
+  }
 
   const WebApp* web_app = GetAppById(app_id);
   CHECK(web_app);
-  return web_app->is_user_selected_app_for_capturing_links();
+  switch (web_app->user_link_capturing_preference()) {
+    case proto::LinkCapturingUserPreference::LINK_CAPTURING_PREFERENCE_DEFAULT:
+      if (!features::kLinksCapturedByDefault.Get()) {
+        return false;
+      }
+      break;
+    case proto::LinkCapturingUserPreference::CAPTURE_SUPPORTED_LINKS:
+      return true;
+    case proto::LinkCapturingUserPreference::DO_NOT_CAPTURE_SUPPORTED_LINKS:
+      return false;
+  }
+
+  // Reaching here means that the default link capturing behavior is 'on' and
+  // the current app is 'default'. To resolve,
+  // - If any other app shares the scope and has link capturing enabled, return
+  //   false.
+  // - If there are more than one apps set to 'default', then return one app
+  //   deterministically (the earliest installed).
+  // Technically, this violates some of the locking practices we have, as this
+  // views all apps instead of the one app. However, given the rarity of hitting
+  // this, and the difficulty of actually hitting an edge case here, this seems
+  // OK.
+  std::vector<std::pair<webapps::AppId, base::Time>> app_and_install_time = {
+      {app_id, web_app->first_install_time()}};
+  for (const webapps::AppId& other_app_id : GetAppIds()) {
+    if (!CanCaptureLinksInScope(other_app_id) || other_app_id == app_id) {
+      continue;
+    }
+    if (!AppScopesMatchForUserLinkCapturing(app_id, other_app_id)) {
+      continue;
+    }
+    const WebApp* other_app = GetAppById(other_app_id);
+    switch (other_app->user_link_capturing_preference()) {
+      case proto::LinkCapturingUserPreference::
+          LINK_CAPTURING_PREFERENCE_DEFAULT:
+        app_and_install_time.emplace_back(other_app_id,
+                                          other_app->first_install_time());
+        break;
+      case proto::LinkCapturingUserPreference::CAPTURE_SUPPORTED_LINKS:
+        return false;
+      case proto::LinkCapturingUserPreference::DO_NOT_CAPTURE_SUPPORTED_LINKS:
+        continue;
+    }
+  }
+
+  // Sort by install time so the first installation wins.
+  std::sort(app_and_install_time.begin(), app_and_install_time.end(),
+            [](auto& left, auto& right) { return left.second < right.second; });
+  return app_and_install_time.front().first == app_id;
 }
 
 absl::optional<webapps::AppId> WebAppRegistrar::FindAppThatCapturesLinksInScope(
@@ -1015,7 +1076,7 @@
   size_t top_score = 0;
   std::vector<webapps::AppId> top_apps;
   for (const webapps::AppId& app_id : GetAppIds()) {
-    if (!IsLocallyInstalled(app_id)) {
+    if (!CanCaptureLinksInScope(app_id)) {
       continue;
     }
     // TODO(dmurph): Switch to GetAppExtendedScopeScore if the
@@ -1069,23 +1130,15 @@
   }
 
   for (const auto& id : GetAppIds()) {
-    // Do not include the same id as the input.
     if (id == app_id) {
       continue;
     }
-
-    // Shortcut apps do not have a scope defined.
-    if (IsShortcutApp(id)) {
+    if (!CanCaptureLinksInScope(id)) {
       continue;
     }
-
-    // Filter out apps whose scopes do not match.
     if (!AppScopesMatchForUserLinkCapturing(id, app_id)) {
       continue;
     }
-
-    // If the app does not capture links in scope, do not take it into
-    // account.
     if (!CapturesLinksInScope(id)) {
       continue;
     }
diff --git a/chrome/browser/web_applications/web_app_registrar.h b/chrome/browser/web_applications/web_app_registrar.h
index aa37f88..1eb63d8 100644
--- a/chrome/browser/web_applications/web_app_registrar.h
+++ b/chrome/browser/web_applications/web_app_registrar.h
@@ -419,6 +419,11 @@
       const IsolatedWebAppUrlInfo& url_info,
       const std::string& partition_name);
 
+  // Returns if the given app_id would ever be eligible to capture links in
+  // its scope. This returns false for apps that aren't installed or for
+  // "Create Shortcut..." apps.
+  bool CanCaptureLinksInScope(const webapps::AppId& app_id) const;
+
   // Returns true if a web app is set to be the default app to
   // capture links by the user. If an app is not locally installed or is a
   // shortcut, this returns false.
@@ -438,7 +443,7 @@
   // Note: This does NOT mean that `app` has user link capturing enabled.
   bool IsLinkCapturableByApp(const webapps::AppId& app, const GURL& url) const;
 
-  // Returns a set of app ids that match the scope for user link capturing.
+  // Returns a set of app ids that match the scope for user link capturing that
   std::vector<webapps::AppId> GetOverlappingAppsMatchingScope(
       const webapps::AppId& app_id) const;
 
@@ -599,6 +604,13 @@
   bool registry_profile_being_deleted_ = false;
 
  private:
+  // Returns if the given app_id is the most recently installed application of
+  // the set of other apps with matching scopes, AND no other app has user link
+  // capturing explicitly turned on. Note that this doesn't consider the link
+  // capturing preference of the `app_id`.
+  bool ShouldCaptureLinksConsiderOverlappingScopes(
+      const webapps::AppId& app_id);
+
   const raw_ptr<Profile> profile_;
   raw_ptr<WebAppProvider> provider_ = nullptr;
 
diff --git a/chrome/browser/web_applications/web_app_registrar_unittest.cc b/chrome/browser/web_applications/web_app_registrar_unittest.cc
index 66e04cd..ee87d492 100644
--- a/chrome/browser/web_applications/web_app_registrar_unittest.cc
+++ b/chrome/browser/web_applications/web_app_registrar_unittest.cc
@@ -22,11 +22,13 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_future.h"
 #include "build/chromeos_buildflags.h"
+#include "chrome/browser/apps/link_capturing/link_capturing_feature_test_support.h"
 #include "chrome/browser/web_applications/commands/run_on_os_login_command.h"
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_location.h"
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
 #include "chrome/browser/web_applications/policy/web_app_policy_manager.h"
+#include "chrome/browser/web_applications/proto/web_app_proto_package.pb.h"
 #include "chrome/browser/web_applications/test/fake_web_app_database_factory.h"
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
 #include "chrome/browser/web_applications/test/web_app_test.h"
@@ -1274,7 +1276,12 @@
   EXPECT_FALSE(registrar().IsActivelyInstalled(app_id));
 }
 
+// Link capturing preferences & overlapping scopes have custom behavior on CrOS.
+#if !BUILDFLAG(IS_CHROMEOS)
 TEST_F(WebAppRegistrarTest, AppsOverlapIfSharesScope) {
+  base::test::ScopedFeatureList enable_link_capturing;
+  enable_link_capturing.InitWithFeaturesAndParameters(
+      apps::test::GetFeaturesToEnableLinkCapturingUX(), {});
   InitSyncBridge();
 
   // Initialize 2 apps, both having the same scope, and set the second
@@ -1288,8 +1295,8 @@
   auto web_app2 = test::CreateWebApp(GURL("https://example.com/def"),
                                      WebAppManagement::kDefault);
   web_app2->SetScope(GURL("https://example_scope.com"));
-  web_app2->SetIsUserSelectedAppForSupportedLinks(
-      /*is_user_selected_app_for_capturing_links=*/true);
+  web_app2->SetLinkCapturingUserPreference(
+      proto::LinkCapturingUserPreference::CAPTURE_SUPPORTED_LINKS);
 
   const webapps::AppId app_id1 = web_app1->app_id();
   const webapps::AppId app_id2 = web_app2->app_id();
@@ -1313,8 +1320,8 @@
   auto web_app2 = test::CreateWebApp(GURL("https://example.com/def"),
                                      WebAppManagement::kDefault);
   web_app2->SetScope(GURL("https://example_scope.com/nested"));
-  web_app2->SetIsUserSelectedAppForSupportedLinks(
-      /*is_user_selected_app_for_capturing_links=*/true);
+  web_app2->SetLinkCapturingUserPreference(
+      proto::LinkCapturingUserPreference::CAPTURE_SUPPORTED_LINKS);
 
   const webapps::AppId app_id1 = web_app1->app_id();
   const webapps::AppId app_id2 = web_app2->app_id();
@@ -1323,6 +1330,7 @@
 
   EXPECT_TRUE(registrar().GetOverlappingAppsMatchingScope(app_id1).empty());
 }
+#endif  // !BUILDFLAG(IS_CHROMEOS)
 
 class WebAppRegistrarTest_ScopeExtensions : public WebAppRegistrarTest {
  public:
diff --git a/chrome/browser/webid/federated_identity_permission_context.cc b/chrome/browser/webid/federated_identity_permission_context.cc
index b9da0591..1d78047 100644
--- a/chrome/browser/webid/federated_identity_permission_context.cc
+++ b/chrome/browser/webid/federated_identity_permission_context.cc
@@ -15,19 +15,13 @@
 #include "url/origin.h"
 
 namespace {
-const char kActiveSessionIdpKey[] = "identity-provider";
 const char kSharingIdpKey[] = "idp-origin";
 
 }  // namespace
 
 FederatedIdentityPermissionContext::FederatedIdentityPermissionContext(
     content::BrowserContext* browser_context)
-    : active_session_context_(
-          new FederatedIdentityAccountKeyedPermissionContext(
-              browser_context,
-              ContentSettingsType::FEDERATED_IDENTITY_ACTIVE_SESSION,
-              kActiveSessionIdpKey)),
-      sharing_context_(new FederatedIdentityAccountKeyedPermissionContext(
+    : sharing_context_(new FederatedIdentityAccountKeyedPermissionContext(
           browser_context,
           ContentSettingsType::FEDERATED_IDENTITY_SHARING,
           kSharingIdpKey)),
@@ -64,33 +58,6 @@
   idp_signin_status_observer_list_.RemoveObserver(observer);
 }
 
-bool FederatedIdentityPermissionContext::HasActiveSession(
-    const url::Origin& relying_party_requester,
-    const url::Origin& identity_provider,
-    const std::string& account_identifier) {
-  return active_session_context_->HasPermission(
-      relying_party_requester, relying_party_requester, identity_provider,
-      account_identifier);
-}
-
-void FederatedIdentityPermissionContext::GrantActiveSession(
-    const url::Origin& relying_party_requester,
-    const url::Origin& identity_provider,
-    const std::string& account_identifier) {
-  active_session_context_->GrantPermission(
-      relying_party_requester, relying_party_requester, identity_provider,
-      account_identifier);
-}
-
-void FederatedIdentityPermissionContext::RevokeActiveSession(
-    const url::Origin& relying_party_requester,
-    const url::Origin& identity_provider,
-    const std::string& account_identifier) {
-  active_session_context_->RevokePermission(
-      relying_party_requester, relying_party_requester, identity_provider,
-      account_identifier);
-}
-
 bool FederatedIdentityPermissionContext::HasSharingPermission(
     const url::Origin& relying_party_requester,
     const url::Origin& relying_party_embedder,
@@ -150,7 +117,6 @@
 }
 
 void FederatedIdentityPermissionContext::FlushScheduledSaveSettingsCalls() {
-  active_session_context_->FlushScheduledSaveSettingsCalls();
   sharing_context_->FlushScheduledSaveSettingsCalls();
   idp_signin_context_->FlushScheduledSaveSettingsCalls();
   idp_registration_context_->FlushScheduledSaveSettingsCalls();
diff --git a/chrome/browser/webid/federated_identity_permission_context.h b/chrome/browser/webid/federated_identity_permission_context.h
index 9202fa3..6a28929c 100644
--- a/chrome/browser/webid/federated_identity_permission_context.h
+++ b/chrome/browser/webid/federated_identity_permission_context.h
@@ -45,15 +45,6 @@
   void AddIdpSigninStatusObserver(IdpSigninStatusObserver* observer) override;
   void RemoveIdpSigninStatusObserver(
       IdpSigninStatusObserver* observer) override;
-  bool HasActiveSession(const url::Origin& relying_party_requester,
-                        const url::Origin& identity_provider,
-                        const std::string& account_identifier) override;
-  void GrantActiveSession(const url::Origin& relying_party_requester,
-                          const url::Origin& identity_provider,
-                          const std::string& account_identifier) override;
-  void RevokeActiveSession(const url::Origin& relying_party_requester,
-                           const url::Origin& identity_provider,
-                           const std::string& account_identifier) override;
   bool HasSharingPermission(
       const url::Origin& relying_party_requester,
       const url::Origin& relying_party_embedder,
@@ -82,8 +73,6 @@
 
  private:
   std::unique_ptr<FederatedIdentityAccountKeyedPermissionContext>
-      active_session_context_;
-  std::unique_ptr<FederatedIdentityAccountKeyedPermissionContext>
       sharing_context_;
   std::unique_ptr<FederatedIdentityIdentityProviderSigninStatusContext>
       idp_signin_context_;
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index 297774ad..8f6f6b2 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1699271769-ab8287c69c281326ddd414b750a9a19b13caaf90.profdata
+chrome-android32-main-1699293477-4ff17d68ddb72025e317e646b2275ac9fc7c07ed.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 91f8085c..091b09b 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1699271769-e677127a42e55d67a105a3da508057936f0facd8.profdata
+chrome-android64-main-1699293477-b39e0c214d2084d38cde34649d8a18bd11b97855.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index cf3e1f7..a588832e 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1699271769-0ba4682db450259f61f4ca95793e089e22e26b22.profdata
+chrome-linux-main-1699293477-803a19a9768f12f214991ceb2c4794345f61f7ac.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 60ea540..5afcf931 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1699286368-f1fadcb32372055ef1f3b603d2459ddfff655fc4.profdata
+chrome-mac-arm-main-1699307946-8ed71622e381c354d8840b86277ce43e9f67a852.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 0dbdaf5..b4e1d73 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1699271769-c15a0bed1db235b92e098cab7fb31f1caa67db14.profdata
+chrome-mac-main-1699293477-3ced5de61d2ae45aab086c72fffe81ef7956decf.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index 8cc6719..9b8edb6b 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1699012733-0577d267e495e2bbd0e266016d4d92621ca7066b.profdata
+chrome-win-arm64-main-1699293477-844945c39a972c3ad4ed2ff319078a56c847d209.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index bf6360d1..2e1033f6 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1699271769-7c32034967be5aa85665bf8fed49b4877cad64f5.profdata
+chrome-win32-main-1699293477-b159b1caf91d8ff002a08000a857b9e6e552cff0.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 1800244a..93886b2 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1699271769-ba183339a05941ba0b1af215964a1fd6068d8880.profdata
+chrome-win64-main-1699282682-29c8298d6af070bce04f66d229218f5cb9310694.profdata
diff --git a/chrome/common/extensions/api/autofill_private.idl b/chrome/common/extensions/api/autofill_private.idl
index 13c8679..47723b62 100644
--- a/chrome/common/extensions/api/autofill_private.idl
+++ b/chrome/common/extensions/api/autofill_private.idl
@@ -391,6 +391,11 @@
     // (biometric or screen lock), false otherwise.
     [supportsPromises] static void checkIfDeviceAuthAvailable(
         CheckForDeviceAuthCallback callback);
+
+    // Bulk delete all the CVCs (server and local) from the local webdata
+    // database. For server CVCs, this will also clear them from the Chrome
+    // sync server and thus other devices.
+    static void bulkDeleteAllCvcs();
   };
 
   interface Events {
diff --git a/chrome/common/extensions/api/input_method_private.json b/chrome/common/extensions/api/input_method_private.json
index a1ae717a..6fe3303 100644
--- a/chrome/common/extensions/api/input_method_private.json
+++ b/chrome/common/extensions/api/input_method_private.json
@@ -679,17 +679,6 @@
           }
         ]
       }, {
-        "name": "onTouch",
-        "type": "function",
-        "description": "This event is sent when a touch occurs in a text field. Should only happen after onFocus()",
-        "parameters": [
-          {
-            "$ref": "FocusReason",
-            "name": "pointerType",
-            "description": "Pointer type used to touch the text field"
-          }
-        ]
-      }, {
         "name": "onSettingsChanged",
         "type": "function",
         "description": "This event is sent when the settings for any input method changed. It is sent to all extensions that are listening to this event, and enabled by the user.",
diff --git a/chrome/common/extensions/api/printing_metrics.idl b/chrome/common/extensions/api/printing_metrics.idl
index 777c325..08b10e5 100644
--- a/chrome/common/extensions/api/printing_metrics.idl
+++ b/chrome/common/extensions/api/printing_metrics.idl
@@ -4,7 +4,7 @@
 
 // Use the <code>chrome.printingMetrics</code> API to fetch data about
 // printing usage.
-[platforms=("chromeos", "lacros"),
+[modernised_enums, platforms=("chromeos", "lacros"),
  implemented_in="chrome/browser/chromeos/extensions/printing_metrics/printing_metrics_api.h"]
 namespace printingMetrics {
   // The source of the print job.
diff --git a/chrome/common/extensions/api/processes.idl b/chrome/common/extensions/api/processes.idl
index 129c47c..69a8ef6 100644
--- a/chrome/common/extensions/api/processes.idl
+++ b/chrome/common/extensions/api/processes.idl
@@ -4,6 +4,7 @@
 
 // Use the <code>chrome.processes</code> API to interact with the browser's
 // processes.
+[modernised_enums]
 namespace processes {
   // The types of the browser processes.
   enum ProcessType {
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 2c05b4e..46fa57ca 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -306,6 +306,7 @@
 const char kChromeUIWebAppInternalsHost[] = "web-app-internals";
 const char kChromeUIWebAppInternalsURL[] = "chrome://web-app-internals";
 const char kChromeUIWebUITestHost[] = "webui-test";
+const char kChromeUIUntrustedWebUITestURL[] = "chrome-untrusted://webui-test/";
 #endif
 
 #if BUILDFLAG(PLATFORM_CFM)
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index af0114f..094c6b8f 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -280,6 +280,7 @@
 extern const char kChromeUIWebAppInternalsHost[];
 extern const char kChromeUIWebAppInternalsURL[];
 extern const char kChromeUIWebUITestHost[];
+extern const char kChromeUIUntrustedWebUITestURL[];
 #endif  // BUILDFLAG(IS_ANDROID)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/services/printing/print_backend_service_impl.cc b/chrome/services/printing/print_backend_service_impl.cc
index 32f4923..cc69527 100644
--- a/chrome/services/printing/print_backend_service_impl.cc
+++ b/chrome/services/printing/print_backend_service_impl.cc
@@ -624,7 +624,8 @@
 #endif
 
   context_container->context = PrintingContext::Create(
-      context_container->delegate.get(), /*skip_system_calls=*/false);
+      context_container->delegate.get(),
+      PrintingContext::ProcessBehavior::kOopEnabledPerformSystemCalls);
 
   bool inserted = persistent_printing_contexts_
                       .insert({context_id, std::move(context_container)})
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index a6936ee..2492721 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1602,6 +1602,7 @@
       "//base",
       "//base:i18n",
       "//base/allocator:buildflags",
+      "//base/test:test_proto",
       "//base/test:test_support",
       "//build:branding_buildflags",
       "//build:chromeos_buildflags",
@@ -2373,6 +2374,7 @@
       "../browser/notifications/scheduler/notification_schedule_service_browsertest.cc",
       "../browser/ntp_tiles/ntp_tiles_browsertest.cc",
       "../browser/optimization_guide/hints_fetcher_browsertest.cc",
+      "../browser/optimization_guide/model_execution/model_execution_browsertest.cc",
       "../browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc",
       "../browser/optimization_guide/page_content_annotations_service_browsertest.cc",
       "../browser/optimization_guide/page_text_observer_browsertest.cc",
@@ -9713,6 +9715,7 @@
       "//components/user_education/views:test_support",
       "//components/user_notes/model:unit_tests",
       "//components/web_modal:test_support",
+      "//components/web_package",
       "//content/test:test_support",
       "//ui/base/dragdrop:types",
       "//ui/views",
@@ -10951,6 +10954,7 @@
           "//chrome/browser/ash/crosapi:crosapi",
           "//chrome/browser/ash/system_web_apps/test_support",
           "//chrome/browser/ash/system_web_apps/test_support:test_support_ui",
+          "//chrome/browser/ui/webui/ash/shortcut_customization:test_support",
           "//chromeos/ash/components/standalone_browser",
           "//components/app_constants",
           "//device/udev_linux:test_support",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 02e5ba93..00b9fa2 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -201,6 +201,7 @@
     "javatests/src/org/chromium/chrome/test/transit/BasePageStation.java",
     "javatests/src/org/chromium/chrome/test/transit/ChromeTabbedActivityPublicTransitEntryPoints.java",
     "javatests/src/org/chromium/chrome/test/transit/EntryPageStation.java",
+    "javatests/src/org/chromium/chrome/test/transit/HubStation.java",
     "javatests/src/org/chromium/chrome/test/transit/NewTabPageStation.java",
     "javatests/src/org/chromium/chrome/test/transit/NtpLoadedCondition.java",
     "javatests/src/org/chromium/chrome/test/transit/PageInteractableCondition.java",
@@ -217,6 +218,9 @@
     "//base/test:public_transit_java",
     "//build/android:build_java",
     "//chrome/android:chrome_java",
+    "//chrome/browser/hub:factory_java",
+    "//chrome/browser/hub:java",
+    "//chrome/browser/hub/internal:java",
     "//chrome/browser/tab:java",
     "//chrome/browser/tabmodel:java",
     "//chrome/browser/ui/android/layouts:java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/BasePageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/BasePageStation.java
index 7628308c..f467a61 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/BasePageStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/BasePageStation.java
@@ -71,6 +71,14 @@
         return Trip.goSync(this, destination, (e) -> onView(TAB_SWITCHER_BUTTON).perform(click()));
     }
 
+    /** Opens the hub by pressing the toolbar tab switcher button. */
+    public HubStation openHub() {
+        recheckEnterConditions();
+
+        HubStation destination = new HubStation(mChromeTabbedActivityTestRule);
+        return Trip.goSync(this, destination, (e) -> onView(TAB_SWITCHER_BUTTON).perform(click()));
+    }
+
     protected ChromeTabbedActivity getChromeTabbedActivity() {
         ChromeTabbedActivity activity = mChromeTabbedActivityTestRule.getActivity();
         if (activity == null) {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/HubStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/HubStation.java
new file mode 100644
index 0000000..b56ca827
--- /dev/null
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/HubStation.java
@@ -0,0 +1,90 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.test.transit;
+
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
+import android.view.View;
+
+import org.hamcrest.Matcher;
+
+import org.chromium.base.test.transit.Elements;
+import org.chromium.base.test.transit.TransitStation;
+import org.chromium.base.test.transit.UiThreadCondition;
+import org.chromium.chrome.browser.hub.HubFieldTrial;
+import org.chromium.chrome.browser.hub.R;
+import org.chromium.chrome.browser.layouts.LayoutManager;
+import org.chromium.chrome.browser.layouts.LayoutType;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+
+/** The Hub screen, with several panes and a toolbar. */
+public class HubStation extends TransitStation {
+    // TODO(crbug/1498446): Uncomment once Hub toolbar has a non-zero height.
+    // public static final Matcher<View> HUB_TOOLBAR = withId(R.id.hub_toolbar);
+    public static final Matcher<View> HUB_PANE_HOST = withId(R.id.hub_pane_host);
+
+    private final ChromeTabbedActivityTestRule mChromeTabbedActivityTestRule;
+
+    /**
+     * @params chromeTabbedActivityTestRule The {@link ChromeTabbedActivityTestRule} of the test.
+     */
+    public HubStation(ChromeTabbedActivityTestRule chromeTabbedActivityTestRule) {
+        super();
+        mChromeTabbedActivityTestRule = chromeTabbedActivityTestRule;
+    }
+
+    @Override
+    public void declareElements(Elements.Builder elements) {
+        // TODO(crbug/1498446): Uncomment once Hub toolbar has a non-zero height.
+        // elements.declareView(HUB_TOOLBAR);
+        elements.declareView(HUB_PANE_HOST);
+
+        elements.declareEnterCondition(new HubIsEnabled());
+        elements.declareEnterCondition(new HubLayoutShowing());
+        elements.declareExitCondition(new HubLayoutNotShowing());
+    }
+
+    private class HubIsEnabled extends UiThreadCondition {
+        @Override
+        public boolean check() {
+            return HubFieldTrial.isHubEnabled();
+        }
+
+        @Override
+        public String buildDescription() {
+            return "HubFieldTrial Hub is enabled";
+        }
+    }
+
+    private class HubLayoutShowing extends UiThreadCondition {
+        @Override
+        public boolean check() {
+            LayoutManager layoutManager =
+                    mChromeTabbedActivityTestRule.getActivity().getLayoutManager();
+            return layoutManager.isLayoutVisible(LayoutType.TAB_SWITCHER)
+                    && !layoutManager.isLayoutStartingToShow(LayoutType.TAB_SWITCHER)
+                    && !layoutManager.isLayoutStartingToHide(LayoutType.TAB_SWITCHER);
+        }
+
+        @Override
+        public String buildDescription() {
+            return "LayoutManager is showing TAB_SWITCHER (Hub)";
+        }
+    }
+
+    private class HubLayoutNotShowing extends UiThreadCondition {
+        @Override
+        public boolean check() {
+            LayoutManager layoutManager =
+                    mChromeTabbedActivityTestRule.getActivity().getLayoutManager();
+            return !layoutManager.isLayoutVisible(LayoutType.TAB_SWITCHER);
+        }
+
+        @Override
+        public String buildDescription() {
+            return "LayoutManager is not showing TAB_SWITCHER (Hub)";
+        }
+    }
+}
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/TabSwitcherStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/TabSwitcherStation.java
index 9a9b250..8ba3249d 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/TabSwitcherStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/TabSwitcherStation.java
@@ -17,6 +17,7 @@
 import org.chromium.base.test.transit.TransitStation;
 import org.chromium.base.test.transit.UiThreadCondition;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.hub.HubFieldTrial;
 import org.chromium.chrome.browser.layouts.LayoutManager;
 import org.chromium.chrome.browser.layouts.LayoutType;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
@@ -56,10 +57,23 @@
             }
         }
 
+        elements.declareEnterCondition(new HubIsDisabled());
         elements.declareEnterCondition(new TabSwitcherLayoutShowing());
         elements.declareExitCondition(new TabSwitcherLayoutNotShowing());
     }
 
+    private class HubIsDisabled extends UiThreadCondition {
+        @Override
+        public boolean check() {
+            return !HubFieldTrial.isHubEnabled();
+        }
+
+        @Override
+        public String buildDescription() {
+            return "HubFieldTrial Hub is disabled";
+        }
+    }
+
     private class TabSwitcherLayoutShowing extends UiThreadCondition {
         @Override
         public boolean check() {
diff --git a/chrome/test/base/chrome_render_view_host_test_harness.cc b/chrome/test/base/chrome_render_view_host_test_harness.cc
index 99c2a61..e252c59 100644
--- a/chrome/test/base/chrome_render_view_host_test_harness.cc
+++ b/chrome/test/base/chrome_render_view_host_test_harness.cc
@@ -48,8 +48,7 @@
   builder.SetIsMainProfile(is_main_profile);
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 
-  for (auto& pair : GetTestingFactories())
-    builder.AddTestingFactory(pair.first, pair.second);
+  builder.AddTestingFactories(GetTestingFactories());
 
   return builder.Build();
 }
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index f18da83..de31b4d 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -157,6 +157,25 @@
 
 }  // namespace
 
+TestingProfile::TestingFactory::TestingFactory(
+    BrowserContextKeyedServiceFactory* service_factory,
+    BrowserContextKeyedServiceFactory::TestingFactory testing_factory)
+    : service_factory_and_testing_factory(
+          std::pair(service_factory, std::move(testing_factory))) {}
+
+TestingProfile::TestingFactory::TestingFactory(
+    RefcountedBrowserContextKeyedServiceFactory* service_factory,
+    RefcountedBrowserContextKeyedServiceFactory::TestingFactory testing_factory)
+    : service_factory_and_testing_factory(
+          std::pair(service_factory, std::move(testing_factory))) {}
+
+TestingProfile::TestingFactory::TestingFactory(const TestingFactory&) = default;
+
+TestingProfile::TestingFactory& TestingProfile::TestingFactory::operator=(
+    const TestingFactory&) = default;
+
+TestingProfile::TestingFactory::~TestingFactory() = default;
+
 // static
 const char TestingProfile::kDefaultProfileUserName[] = "testing_profile@test";
 
@@ -247,8 +266,11 @@
   }
 
   // Set any testing factories prior to initializing the services.
-  for (TestingFactories::value_type& pair : testing_factories)
-    pair.first->SetTestingFactory(this, std::move(pair.second));
+  for (const auto& f : testing_factories) {
+    absl::visit(
+        [this](const auto& p) { p.first->SetTestingFactory(this, p.second); },
+        f.service_factory_and_testing_factory);
+  }
   testing_factories.clear();
 
   Init(is_supervised_profile);
@@ -1104,6 +1126,14 @@
   return *this;
 }
 
+TestingProfile::Builder& TestingProfile::Builder::AddTestingFactory(
+    RefcountedBrowserContextKeyedServiceFactory* service_factory,
+    RefcountedBrowserContextKeyedServiceFactory::TestingFactory
+        testing_factory) {
+  testing_factories_.emplace_back(service_factory, std::move(testing_factory));
+  return *this;
+}
+
 TestingProfile::Builder& TestingProfile::Builder::AddTestingFactories(
     const TestingFactories& testing_factories) {
   testing_factories_.insert(testing_factories_.end(), testing_factories.begin(),
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index aeb247f..c54b4beb 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -23,6 +23,7 @@
 #include "components/domain_reliability/clear_mode.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h"
 #include "components/keyed_service/core/simple_dependency_manager.h"
 #include "components/keyed_service/core/simple_factory_key.h"
 #include "components/supervised_user/core/common/buildflags.h"
@@ -30,6 +31,7 @@
 #include "content/public/browser/permission_controller_delegate.h"
 #include "extensions/buildflags/buildflags.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
@@ -86,9 +88,27 @@
   // Default constructor that cannot be used with multi-profiles.
   TestingProfile();
 
-  using TestingFactories =
-      std::vector<std::pair<BrowserContextKeyedServiceFactory*,
-                            BrowserContextKeyedServiceFactory::TestingFactory>>;
+  // Wrapper over absl::variant to help type deduction when calling
+  // AddTestingFactories(). See example call in the method's comment.
+  struct TestingFactory {
+    TestingFactory(
+        BrowserContextKeyedServiceFactory* service_factory,
+        BrowserContextKeyedServiceFactory::TestingFactory testing_factory);
+    TestingFactory(RefcountedBrowserContextKeyedServiceFactory* service_factory,
+                   RefcountedBrowserContextKeyedServiceFactory::TestingFactory
+                       testing_factory);
+    TestingFactory(const TestingFactory&);
+    TestingFactory& operator=(const TestingFactory&);
+    ~TestingFactory();
+
+    absl::variant<
+        std::pair<BrowserContextKeyedServiceFactory*,
+                  BrowserContextKeyedServiceFactory::TestingFactory>,
+        std::pair<RefcountedBrowserContextKeyedServiceFactory*,
+                  RefcountedBrowserContextKeyedServiceFactory::TestingFactory>>
+        service_factory_and_testing_factory;
+  };
+  using TestingFactories = std::vector<TestingFactory>;
 
   // Helper class for building an instance of TestingProfile (allows injecting
   // mocks for various services prior to profile initialization).
@@ -113,9 +133,18 @@
     Builder& AddTestingFactory(
         BrowserContextKeyedServiceFactory* service_factory,
         BrowserContextKeyedServiceFactory::TestingFactory testing_factory);
+    Builder& AddTestingFactory(
+        RefcountedBrowserContextKeyedServiceFactory* service_factory,
+        RefcountedBrowserContextKeyedServiceFactory::TestingFactory
+            testing_factory);
 
     // Add multiple testing factories to the TestingProfile. These testing
     // factories are applied before the ProfileKeyedServices are created.
+    // Example use:
+    //
+    // AddTestingFactories(
+    //     {{RegularServiceFactory::GetInstance(), test_factory1},
+    //      {RefcountedServiceFactory::GetInstance(), test_factory2}});
     Builder& AddTestingFactories(const TestingFactories& testing_factories);
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/test/base/testing_profile_manager.cc b/chrome/test/base/testing_profile_manager.cc
index e434b14..87da3c4 100644
--- a/chrome/test/base/testing_profile_manager.cc
+++ b/chrome/test/base/testing_profile_manager.cc
@@ -132,8 +132,7 @@
   builder.SetIsMainProfile(is_main_profile);
 #endif
 
-  for (TestingProfile::TestingFactories::value_type& pair : testing_factories)
-    builder.AddTestingFactory(pair.first, std::move(pair.second));
+  builder.AddTestingFactories(testing_factories);
   testing_factories.clear();
 
   builder.SetSharedURLLoaderFactory(shared_url_loader_factory);
diff --git a/chrome/test/base/web_ui_mocha_browser_test.cc b/chrome/test/base/web_ui_mocha_browser_test.cc
index ca52650..20d8c97 100644
--- a/chrome/test/base/web_ui_mocha_browser_test.cc
+++ b/chrome/test/base/web_ui_mocha_browser_test.cc
@@ -19,6 +19,7 @@
 #include "chrome/test/base/web_ui_test_data_source.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/common/page_type.h"
+#include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "url/gurl.h"
@@ -40,7 +41,8 @@
 }  // namespace
 
 WebUIMochaBrowserTest::WebUIMochaBrowserTest()
-    : test_loader_host_(chrome::kChromeUIWebUITestHost) {}
+    : test_loader_host_(chrome::kChromeUIWebUITestHost),
+      test_loader_scheme_(content::kChromeUIScheme) {}
 
 WebUIMochaBrowserTest::~WebUIMochaBrowserTest() = default;
 
@@ -48,6 +50,13 @@
   test_loader_host_ = host;
 }
 
+void WebUIMochaBrowserTest::set_test_loader_scheme(const std::string& scheme) {
+  // Only chrome:// and chrome-untrusted:// are supported.
+  CHECK(scheme == content::kChromeUIScheme ||
+        scheme == content::kChromeUIUntrustedScheme);
+  test_loader_scheme_ = scheme;
+}
+
 content::WebContents* WebUIMochaBrowserTest::GetWebContentsForSetup() {
   return chrome_test_utils::GetActiveWebContents(this);
 }
@@ -64,7 +73,12 @@
   content::WebContents* web_contents = GetWebContentsForSetup();
   Profile* profile =
       Profile::FromBrowserContext(web_contents->GetBrowserContext());
-  webui::CreateAndAddWebUITestDataSource(profile);
+  if (test_loader_scheme_ == content::kChromeUIScheme) {
+    webui::CreateAndAddWebUITestDataSource(profile);
+  } else {
+    // Must be untrusted
+    webui::CreateAndAddUntrustedWebUITestDataSource(profile);
+  }
 
   // Necessary setup for reporting code coverage metrics.
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -93,9 +107,9 @@
   // Construct URL to load the test module file.
   GURL url(
       skip_test_loader
-          ? std::string("chrome://" + test_loader_host_)
+          ? std::string(test_loader_scheme_ + "://" + test_loader_host_)
           : std::string(
-                "chrome://" + test_loader_host_ +
+                test_loader_scheme_ + "://" + test_loader_host_ +
                 "/test_loader.html?adapter=mocha_adapter_simple.js&module=") +
                 file);
 
@@ -178,8 +192,8 @@
   std::string loadMochaScript(base::StringPrintf(
       R"(
 async function load() {
-  await import('chrome://%s/mocha.js');
-  await import('chrome://%s/mocha_adapter_simple.js');
+  await import('//%s/mocha.js');
+  await import('//%s/mocha_adapter_simple.js');
 }
 load();
 )",
@@ -192,9 +206,8 @@
   }
 
   // Step 2: Programmatically loads the Mocha test file.
-  std::string loadTestModuleScript(
-      base::StringPrintf("import('chrome://%s/%s');",
-                         chrome::kChromeUIWebUITestHost, file.c_str()));
+  std::string loadTestModuleScript(base::StringPrintf(
+      "import('//%s/%s');", chrome::kChromeUIWebUITestHost, file.c_str()));
   return ExecJs(web_contents->GetPrimaryMainFrame(), loadTestModuleScript);
 }
 
diff --git a/chrome/test/base/web_ui_mocha_browser_test.h b/chrome/test/base/web_ui_mocha_browser_test.h
index f73bb136a..829030c 100644
--- a/chrome/test/base/web_ui_mocha_browser_test.h
+++ b/chrome/test/base/web_ui_mocha_browser_test.h
@@ -69,6 +69,7 @@
   void SetUpOnMainThread() override;
 
   void set_test_loader_host(const std::string& host);
+  void set_test_loader_scheme(const std::string& scheme);
 
  private:
   // Helper that performs setup steps normally done by test_loader.html, invoked
@@ -85,6 +86,12 @@
   // Note: It is also used by RunTest even when |skip_test_loader| is true.
   std::string test_loader_host_;
 
+  // The scheme to use when invoking the test_loader URL, like
+  // "<scheme>://webui-test/test_loader.html=...". Defaults to
+  // content::kChromeUIScheme.
+  // Note: It is also used by RunTest even when |skip_test_loader| is true.
+  std::string test_loader_scheme_;
+
   // Handles collection of code coverage.
   std::unique_ptr<DevToolsAgentCoverageObserver> coverage_handler_;
 };
diff --git a/chrome/test/base/web_ui_test_data_source.cc b/chrome/test/base/web_ui_test_data_source.cc
index 40755d9..c8e73d46 100644
--- a/chrome/test/base/web_ui_test_data_source.cc
+++ b/chrome/test/base/web_ui_test_data_source.cc
@@ -4,12 +4,14 @@
 
 #include "chrome/test/base/web_ui_test_data_source.h"
 
+#include "base/strings/stringprintf.h"
 #include "chrome/browser/ui/webui/webui_util.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/test/data/grit/webui_test_resources.h"
 #include "chrome/test/data/grit/webui_test_resources_map.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/url_constants.h"
 #include "services/network/public/mojom/content_security_policy.mojom.h"
 #include "ui/resources/grit/webui_resources.h"
 
@@ -17,13 +19,10 @@
 #include "ash/webui/common/trusted_types_util.h"
 #endif
 
-namespace webui {
+namespace {
 
-content::WebUIDataSource* CreateAndAddWebUITestDataSource(
-    content::BrowserContext* browser_context) {
-  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
-      browser_context, chrome::kChromeUIWebUITestHost);
-
+void SetupTestDataSource(content::WebUIDataSource* source,
+                         const std::string& scheme) {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   ash::EnableTrustedTypesCSP(source);
 #else
@@ -32,13 +31,13 @@
 
   source->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::ScriptSrc,
-      "script-src chrome://* 'self';");
+      base::StringPrintf("script-src %s://* 'self';", scheme.c_str()));
   source->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::WorkerSrc,
-      "worker-src blob: chrome://* 'self';");
+      base::StringPrintf("worker-src blob: %s://* 'self';", scheme.c_str()));
   source->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::FrameAncestors,
-      "frame-ancestors chrome://* 'self';");
+      base::StringPrintf("frame-ancestors %s://* 'self';", scheme.c_str()));
 
   source->AddResourcePaths(
       base::make_span(kWebuiTestResources, kWebuiTestResourcesSize));
@@ -46,7 +45,27 @@
   source->AddResourcePath("test_loader_util.js",
                           IDR_WEBUI_JS_TEST_LOADER_UTIL_JS);
   source->AddResourcePath("test_loader.html", IDR_WEBUI_TEST_LOADER_HTML);
+}
 
+}  // namespace
+
+namespace webui {
+
+content::WebUIDataSource* CreateAndAddWebUITestDataSource(
+    content::BrowserContext* browser_context) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      browser_context, chrome::kChromeUIWebUITestHost);
+
+  SetupTestDataSource(source, content::kChromeUIScheme);
+  return source;
+}
+
+content::WebUIDataSource* CreateAndAddUntrustedWebUITestDataSource(
+    content::BrowserContext* browser_context) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      browser_context, chrome::kChromeUIUntrustedWebUITestURL);
+
+  SetupTestDataSource(source, content::kChromeUIUntrustedScheme);
   return source;
 }
 
diff --git a/chrome/test/base/web_ui_test_data_source.h b/chrome/test/base/web_ui_test_data_source.h
index 5d169cf..aefbed8 100644
--- a/chrome/test/base/web_ui_test_data_source.h
+++ b/chrome/test/base/web_ui_test_data_source.h
@@ -17,6 +17,10 @@
 content::WebUIDataSource* CreateAndAddWebUITestDataSource(
     content::BrowserContext* browser_context);
 
+// Creates a data source for for chrome-untrusted://webui-test/ URLs.
+content::WebUIDataSource* CreateAndAddUntrustedWebUITestDataSource(
+    content::BrowserContext* browser_context);
+
 }  // namespace webui
 
 #endif  // CHROME_TEST_BASE_WEB_UI_TEST_DATA_SOURCE_H_
diff --git a/chrome/test/data/extensions/api_test/autofill_private/test.js b/chrome/test/data/extensions/api_test/autofill_private/test.js
index 49773a0..aa06cc86 100644
--- a/chrome/test/data/extensions/api_test/autofill_private/test.js
+++ b/chrome/test/data/extensions/api_test/autofill_private/test.js
@@ -579,6 +579,12 @@
               }));
         }));
   },
+
+  function bulkDeleteAllCvcs() {
+    chrome.autofillPrivate.bulkDeleteAllCvcs();
+    chrome.test.assertNoLastError();
+    chrome.test.succeed();
+  },
 ];
 
 /** @const */
@@ -601,6 +607,7 @@
   'authenticateUserAndFlipMandatoryAuthToggle':
       ['authenticateUserAndFlipMandatoryAuthToggle'],
   'getLocalCard': ['addNewCreditCard', 'getLocalCard'],
+  'bulkDeleteAllCvcs': ['bulkDeleteAllCvcs'],
 };
 
 var testConfig = window.location.search.substring(1);
diff --git a/chrome/test/data/pdf/metrics_test.ts b/chrome/test/data/pdf/metrics_test.ts
index a3cc509..c0c7fc2 100644
--- a/chrome/test/data/pdf/metrics_test.ts
+++ b/chrome/test/data/pdf/metrics_test.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 {FittingType, record, recordFitTo, resetForTesting, UserAction} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_viewer_wrapper.js';
+import {FittingType, record, recordFitTo, resetForTesting as resetMetricsForTesting, UserAction} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_viewer_wrapper.js';
 
 chrome.test.runTests(function() {
   'use strict';
@@ -32,7 +32,7 @@
 
   return [
     function testMetricsDocumentOpened() {
-      resetForTesting();
+      resetMetricsForTesting();
       const mockMetricsPrivate = new MockMetricsPrivate();
       chrome.metricsPrivate =
           mockMetricsPrivate as unknown as typeof chrome.metricsPrivate;
@@ -48,7 +48,7 @@
     // Test that for every UserAction.<action> recorded an equivalent
     // UserAction.<action>_FIRST is recorded only once.
     function testMetricsFirstRecorded() {
-      resetForTesting();
+      resetMetricsForTesting();
       const mockMetricsPrivate = new MockMetricsPrivate();
       chrome.metricsPrivate =
           mockMetricsPrivate as unknown as typeof chrome.metricsPrivate;
@@ -80,7 +80,7 @@
     },
 
     function testMetricsFitTo() {
-      resetForTesting();
+      resetMetricsForTesting();
       const mockMetricsPrivate = new MockMetricsPrivate();
       chrome.metricsPrivate =
           mockMetricsPrivate as unknown as typeof chrome.metricsPrivate;
diff --git a/chrome/test/data/web_apps/empty_web_app.json b/chrome/test/data/web_apps/empty_web_app.json
index 675754cf..635db73 100644
--- a/chrome/test/data/web_apps/empty_web_app.json
+++ b/chrome/test/data/web_apps/empty_web_app.json
@@ -31,7 +31,6 @@
    "is_generated_icon": false,
    "is_locally_installed": false,
    "is_uninstalling": false,
-   "is_user_selected_app_for_capturing_links": false,
    "isolation_data": null,
    "last_badging_time": "1601-01-01 00:00:00.000000 UTC",
    "last_launch_time": "1601-01-01 00:00:00.000000 UTC",
@@ -71,6 +70,7 @@
    "url_handlers": [  ],
    "user_display_mode": null,
    "user_launch_ordinal": "INVALID[]",
+   "user_link_capturing_preference": "0",
    "user_page_ordinal": "INVALID[]",
    "window_controls_overlay_enabled": false
 }
diff --git a/chrome/test/data/web_apps/sample_web_app.json b/chrome/test/data/web_apps/sample_web_app.json
index dbe52ed..8c32e8d 100644
--- a/chrome/test/data/web_apps/sample_web_app.json
+++ b/chrome/test/data/web_apps/sample_web_app.json
@@ -164,16 +164,15 @@
    } ],
    "first_install_time": "1970-01-27 09:52:51.713000 UTC",
    "generated_icon_fix": {
-      "attempt_count": 49,
-      "last_attempt_time": "1970-01-27 13:51:34.772000 UTC",
+      "attempt_count": 6,
+      "last_attempt_time": "1970-02-16 01:03:53.549000 UTC",
       "source": "Retroactive",
-      "window_start_time": "1970-02-08 13:02:14.367000 UTC"
+      "window_start_time": "1970-01-27 13:51:34.772000 UTC"
    },
    "is_from_sync_and_pending_installation": true,
    "is_generated_icon": true,
    "is_locally_installed": true,
    "is_uninstalling": false,
-   "is_user_selected_app_for_capturing_links": true,
    "isolation_data": {
       "controlled_frame_partitions (on-disk)": [ "partition_name" ],
       "isolated_web_app_location": {
@@ -194,7 +193,7 @@
    "last_badging_time": "1970-02-06 10:58:36.765000 UTC",
    "last_launch_time": "1970-01-28 05:07:28.623000 UTC",
    "latest_install_source": "external lock screen",
-   "latest_install_time": "1970-02-05 16:23:32.767000 UTC",
+   "latest_install_time": "1970-01-06 12:19:09.338000 UTC",
    "launch_handler": {
       "client_mode": "kNavigateExisting"
    },
@@ -421,8 +420,8 @@
    } ],
    "sources": [ "System", "Kiosk", "Policy", "OEM", "SubApp", "WebAppStore", "OneDriveIntegration", "Sync", "CommandLine", "ApsDefault", "Default" ],
    "start_url": "https://example.com/scope1234/start1234",
-   "supported_links_offer_dismiss_count": 445271870,
-   "supported_links_offer_ignore_count": 716143606,
+   "supported_links_offer_dismiss_count": -1701779570,
+   "supported_links_offer_ignore_count": 445271870,
    "sync_fallback_data": {
       "manifest_icons": [ {
          "purpose": "kAny",
@@ -489,6 +488,7 @@
    } ],
    "user_display_mode": "kTabbed",
    "user_launch_ordinal": "INVALID[]",
+   "user_link_capturing_preference": "1",
    "user_page_ordinal": "INVALID[]",
    "window_controls_overlay_enabled": false
 }
diff --git a/chrome/test/data/webui/build_webui_tests.gni b/chrome/test/data/webui/build_webui_tests.gni
index 042f939b..5d870dc 100644
--- a/chrome/test/data/webui/build_webui_tests.gni
+++ b/chrome/test/data/webui/build_webui_tests.gni
@@ -73,9 +73,15 @@
     if (defined(invoker.ts_path_mappings)) {
       path_mappings += invoker.ts_path_mappings
     }
-    path_mappings += [ "chrome://webui-test/*|" +
-                       rebase_path("$root_gen_dir/chrome/test/data/webui/tsc/*",
-                                   target_gen_dir) ]
+    if (defined(invoker.is_chrome_untrusted) && invoker.is_chrome_untrusted) {
+      path_mappings += [ "chrome-untrusted://webui-test/*|" + rebase_path(
+                             "$root_gen_dir/chrome/test/data/webui/tsc/*",
+                             target_gen_dir) ]
+    } else {
+      path_mappings += [ "chrome://webui-test/*|" + rebase_path(
+                             "$root_gen_dir/chrome/test/data/webui/tsc/*",
+                             target_gen_dir) ]
+    }
     in_files = files
 
     if (defined(invoker.ts_definitions)) {
diff --git a/chrome/test/data/webui/chromeos/ash_common/list_property_update_behavior_test.ts b/chrome/test/data/webui/chromeos/ash_common/list_property_update_behavior_test.ts
index adb8c2d..5618b22 100644
--- a/chrome/test/data/webui/chromeos/ash_common/list_property_update_behavior_test.ts
+++ b/chrome/test/data/webui/chromeos/ash_common/list_property_update_behavior_test.ts
@@ -288,8 +288,8 @@
       function() {
         // Ensure that the |words| property of a |complexArray| element is
         // updated properly.
-        let newArray = JSON.parse(JSON.stringify(testElement.complexArray));
-        newArray[1].words = newArray[1].words.slice(0, 2);
+        let newArray = structuredClone(testElement.complexArray);
+        newArray[1]!.words = newArray[1]!.words.slice(0, 2);
         let result = testElement.updateComplexArray(newArray);
 
         assertFalse(result.topArrayChanged);
@@ -299,10 +299,10 @@
         // Ensure that the array is properly updated when the |words| array of
         // multiple elements are modified.
         testElement.resetComplexArray();
-        newArray = JSON.parse(JSON.stringify(testElement.complexArray));
-        newArray[0].words.push('apricot');
-        newArray[1].words = newArray[1].words.slice(1);
-        newArray[2].words.push('circus', 'citrus', 'carrot');
+        newArray = structuredClone(testElement.complexArray);
+        newArray[0]!.words.push('apricot');
+        newArray[1]!.words = newArray[1]!.words.slice(1);
+        newArray[2]!.words.push('circus', 'citrus', 'carrot');
         result = testElement.updateComplexArray(newArray);
 
         assertFalse(result.topArrayChanged);
@@ -311,20 +311,20 @@
       });
 
   test('first item with same uid modified', () => {
-    const newArray = JSON.parse(JSON.stringify(testElement.complexArray));
-    assertTrue(newArray[0].words.length > 0);
-    assertNotEquals('apricot', newArray[0].words[0]);
-    newArray[0].words = ['apricot'];
+    const newArray = structuredClone(testElement.complexArray);
+    assertTrue(newArray[0]!.words.length > 0);
+    assertNotEquals('apricot', newArray[0]!.words[0]);
+    newArray[0]!.words = ['apricot'];
     assertTrue(testElement.updateList(
         'complexArray', (x: ComplexArrayEntry) => x.letter, newArray));
     assertDeepEquals(['apricot'], testElement.complexArray[0]!.words);
   });
 
   test('first item modified with same uid and last item removed', () => {
-    const newArray = JSON.parse(JSON.stringify(testElement.complexArray));
-    assertTrue(newArray[0].words.length > 0);
-    assertNotEquals('apricot', newArray[0].words[0]);
-    newArray[0].words = ['apricot'];
+    const newArray = structuredClone(testElement.complexArray);
+    assertTrue(newArray[0]!.words.length > 0);
+    assertNotEquals('apricot', newArray[0]!.words[0]);
+    newArray[0]!.words = ['apricot'];
     assertTrue(newArray.length > 1);
     newArray.pop();
     assertTrue(testElement.updateList(
diff --git a/chrome/test/data/webui/compose/compose_app_test.ts b/chrome/test/data/webui/compose/compose_app_test.ts
index 3b07e20..d93f360 100644
--- a/chrome/test/data/webui/compose/compose_app_test.ts
+++ b/chrome/test/data/webui/compose/compose_app_test.ts
@@ -165,6 +165,15 @@
     assertTrue(
         isVisible(app.$.refreshButton), 'Refresh button should be visible.');
 
+    // Mock changing length and tone to verify they are unset after hitting
+    // the refresh button.
+    app.$.lengthMenu.value = `${Length.kShorter}`;
+    app.$.lengthMenu.dispatchEvent(new CustomEvent('change'));
+    app.$.toneMenu.value = `${Tone.kCasual}`;
+    app.$.toneMenu.dispatchEvent(new CustomEvent('change'));
+    await flushTasks();
+    testProxy.resetResolver('compose');
+
     // Click the refresh button and assert compose is called with the same args.
     app.$.refreshButton.click();
     assertTrue(
diff --git a/chrome/test/data/webui/cr_elements/list_property_update_mixin_test.ts b/chrome/test/data/webui/cr_elements/list_property_update_mixin_test.ts
index 4941a17..072b20c 100644
--- a/chrome/test/data/webui/cr_elements/list_property_update_mixin_test.ts
+++ b/chrome/test/data/webui/cr_elements/list_property_update_mixin_test.ts
@@ -286,8 +286,8 @@
       function() {
         // Ensure that the |words| property of a |complexArray| element is
         // updated properly.
-        let newArray = JSON.parse(JSON.stringify(testElement.complexArray));
-        newArray[1].words = newArray[1].words.slice(0, 2);
+        let newArray = structuredClone(testElement.complexArray);
+        newArray[1]!.words = newArray[1]!.words.slice(0, 2);
         let result = testElement.updateComplexArray(newArray);
 
         assertFalse(result.topArrayChanged);
@@ -297,10 +297,10 @@
         // Ensure that the array is properly updated when the |words| array of
         // multiple elements are modified.
         testElement.resetComplexArray();
-        newArray = JSON.parse(JSON.stringify(testElement.complexArray));
-        newArray[0].words.push('apricot');
-        newArray[1].words = newArray[1].words.slice(1);
-        newArray[2].words.push('circus', 'citrus', 'carrot');
+        newArray = structuredClone(testElement.complexArray);
+        newArray[0]!.words.push('apricot');
+        newArray[1]!.words = newArray[1]!.words.slice(1);
+        newArray[2]!.words.push('circus', 'citrus', 'carrot');
         result = testElement.updateComplexArray(newArray);
 
         assertFalse(result.topArrayChanged);
@@ -309,20 +309,20 @@
       });
 
   test('first item with same uid modified', () => {
-    const newArray = JSON.parse(JSON.stringify(testElement.complexArray));
-    assertTrue(newArray[0].words.length > 0);
-    assertNotEquals('apricot', newArray[0].words[0]);
-    newArray[0].words = ['apricot'];
+    const newArray = structuredClone(testElement.complexArray);
+    assertTrue(newArray[0]!.words.length > 0);
+    assertNotEquals('apricot', newArray[0]!.words[0]);
+    newArray[0]!.words = ['apricot'];
     assertTrue(testElement.updateList(
         'complexArray', (x: ComplexArrayEntry) => x.letter, newArray));
     assertDeepEquals(['apricot'], testElement.complexArray[0]!.words);
   });
 
   test('first item modified with same uid and last item removed', () => {
-    const newArray = JSON.parse(JSON.stringify(testElement.complexArray));
-    assertTrue(newArray[0].words.length > 0);
-    assertNotEquals('apricot', newArray[0].words[0]);
-    newArray[0].words = ['apricot'];
+    const newArray = structuredClone(testElement.complexArray);
+    assertTrue(newArray[0]!.words.length > 0);
+    assertNotEquals('apricot', newArray[0]!.words[0]);
+    newArray[0]!.words = ['apricot'];
     assertTrue(newArray.length > 1);
     newArray.pop();
     assertTrue(testElement.updateList(
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn
index 6dc4e5c..978701d0 100644
--- a/chrome/test/data/webui/settings/BUILD.gn
+++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -8,6 +8,7 @@
   files = [
     "about_page_test.ts",
     "advanced_page_test.ts",
+    "ai_page_test.ts",
     "all_sites_test.ts",
     "anti_abuse_page_test.ts",
     "appearance_fonts_page_test.ts",
diff --git a/chrome/test/data/webui/settings/ai_page_test.ts b/chrome/test/data/webui/settings/ai_page_test.ts
new file mode 100644
index 0000000..a0a11c7
--- /dev/null
+++ b/chrome/test/data/webui/settings/ai_page_test.ts
@@ -0,0 +1,194 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'chrome://settings/settings.js';
+
+import {LifetimeBrowserProxyImpl, SettingsAiPageFeaturePrefName as PrefName, SettingsToggleButtonElement, SettingsAiPageElement, CrSettingsPrefs, SettingsPrefsElement, loadTimeData, FeatureOptInState} from 'chrome://settings/settings.js';
+
+import {assertEquals, assertTrue, assertFalse} from 'chrome://webui-test/chai_assert.js';
+import {isVisible} from 'chrome://webui-test/test_util.js';
+import {TestLifetimeBrowserProxy} from './test_lifetime_browser_proxy.js';
+
+suite('ExperimentalAdvancedPage', function() {
+  let page: SettingsAiPageElement;
+  let settingsPrefs: SettingsPrefsElement;
+  let lifetimeBrowserProxy: TestLifetimeBrowserProxy;
+
+  suiteSetup(function() {
+    settingsPrefs = document.createElement('settings-prefs');
+    return CrSettingsPrefs.initialized;
+  });
+
+  function createPage() {
+    lifetimeBrowserProxy = new TestLifetimeBrowserProxy();
+    LifetimeBrowserProxyImpl.setInstance(lifetimeBrowserProxy);
+
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
+    page = document.createElement('settings-ai-page');
+    page.prefs = settingsPrefs.prefs;
+    document.body.appendChild(page);
+  }
+
+  // Test that interacting with the main toggle
+  //  - updates the corresponding pref
+  //  - updates the iron-collapse opened status
+  //  - shows the restart toast
+  test('MainToggle', () => {
+    createPage();
+    page.setPrefValue(PrefName.MAIN, FeatureOptInState.NOT_INITIALIZED);
+
+    const mainToggle = page.shadowRoot!.querySelector('settings-toggle-button');
+    assertTrue(!!mainToggle);
+    const collapse = page.shadowRoot!.querySelector('iron-collapse');
+    assertTrue(!!collapse);
+
+    // Check NOT_INITIALIZED case.
+    assertFalse(mainToggle.checked);
+    assertFalse(collapse.opened);
+    assertFalse(page.$.toast.open);
+
+    // Check ENABLED case.
+    mainToggle.click();
+    assertEquals(FeatureOptInState.ENABLED, page.getPref(PrefName.MAIN).value);
+    assertTrue(mainToggle.checked);
+    assertTrue(collapse.opened);
+    assertTrue(page.$.toast.open);
+
+    // Check DISABLED case.
+    mainToggle.click();
+    assertEquals(FeatureOptInState.DISABLED, page.getPref(PrefName.MAIN).value);
+    assertFalse(mainToggle.checked);
+    assertFalse(collapse.opened);
+    assertTrue(page.$.toast.open);
+  });
+
+  test('FeatureTogglesVisibility', () => {
+    // Case 1, a subset of the controls should be visible.
+    loadTimeData.overrideValues({
+      showComposeControl: true,
+      showTabOrganizationControl: false,
+      showWallpaperSearchControl: false,
+    });
+    createPage();
+
+    // Turn the main pref to ENABLED so that the iron-collapse holding the
+    // feature specific toggles is expanded.
+    page.setPrefValue(PrefName.MAIN, FeatureOptInState.ENABLED);
+
+    let toggles = page.shadowRoot!.querySelectorAll(
+        'iron-collapse settings-toggle-button');
+    assertEquals(3, toggles.length);
+    assertTrue(isVisible(toggles[0]!));
+    assertFalse(isVisible(toggles[1]!));
+    assertFalse(isVisible(toggles[2]!));
+
+    // Case 1, a different subset of the controls should be visible.
+    loadTimeData.overrideValues({
+      showComposeControl: false,
+      showTabOrganizationControl: true,
+      showWallpaperSearchControl: true,
+    });
+    createPage();
+
+    toggles = page.shadowRoot!.querySelectorAll(
+        'iron-collapse settings-toggle-button');
+    assertEquals(3, toggles.length);
+    assertFalse(isVisible(toggles[0]!));
+    assertTrue(isVisible(toggles[1]!));
+    assertTrue(isVisible(toggles[2]!));
+  });
+
+  test('FeatureTogglesInteraction', () => {
+    loadTimeData.overrideValues({
+      showComposeControl: true,
+      showTabOrganizationControl: true,
+      showWallpaperSearchControl: true,
+    });
+    createPage();
+    const toggles =
+        page.shadowRoot!.querySelectorAll<SettingsToggleButtonElement>(
+            'iron-collapse settings-toggle-button');
+    assertEquals(3, toggles.length);
+    assertFalse(page.$.toast.open);
+
+    for (const toggle of toggles) {
+      assertTrue(!!toggle.pref);
+      page.setPrefValue(toggle.pref.key, FeatureOptInState.NOT_INITIALIZED);
+      assertFalse(toggle.checked);
+    }
+
+    function assertPrefs(
+        value1: FeatureOptInState, value2: FeatureOptInState,
+        value3: FeatureOptInState) {
+      assertEquals(value1, page.getPref(PrefName.COMPOSE).value);
+      assertEquals(value2, page.getPref(PrefName.TAB_ORGANIZATION).value);
+      assertEquals(value3, page.getPref(PrefName.WALLPAPER_SEARCH).value);
+    }
+
+    // Check turning on toggles one by one.
+    toggles[0]!.click();
+    assertPrefs(
+        FeatureOptInState.ENABLED, FeatureOptInState.NOT_INITIALIZED,
+        FeatureOptInState.NOT_INITIALIZED);
+    assertTrue(page.$.toast.open);
+
+    // Manually hide toast to test the next toggle, normally stays open.
+    page.$.toast.hide();
+
+    toggles[1]!.click();
+    assertPrefs(
+        FeatureOptInState.ENABLED, FeatureOptInState.ENABLED,
+        FeatureOptInState.NOT_INITIALIZED);
+
+    toggles[2]!.click();
+    assertPrefs(
+        FeatureOptInState.ENABLED, FeatureOptInState.ENABLED,
+        FeatureOptInState.ENABLED);
+    assertTrue(page.$.toast.open);
+    page.$.toast.hide();
+
+    // Check turning off toggles one by one.
+    toggles[0]!.click();
+    assertPrefs(
+        FeatureOptInState.DISABLED, FeatureOptInState.ENABLED,
+        FeatureOptInState.ENABLED);
+    assertTrue(page.$.toast.open);
+    page.$.toast.hide();
+
+    toggles[1]!.click();
+    assertPrefs(
+        FeatureOptInState.DISABLED, FeatureOptInState.DISABLED,
+        FeatureOptInState.ENABLED);
+    assertTrue(page.$.toast.open);
+    page.$.toast.hide();
+
+    toggles[2]!.click();
+    assertPrefs(
+        FeatureOptInState.DISABLED, FeatureOptInState.DISABLED,
+        FeatureOptInState.DISABLED);
+    assertTrue(page.$.toast.open);
+  });
+
+  test('RelaunchToast', () => {
+    loadTimeData.overrideValues({
+      showComposeControl: true,
+      showTabOrganizationControl: true,
+      showWallpaperSearchControl: true,
+    });
+    createPage();
+    const toggle = page.shadowRoot!.querySelector<SettingsToggleButtonElement>(
+        'iron-collapse settings-toggle-button');
+    assertTrue(!!toggle);
+    assertFalse(toggle.checked);
+    assertFalse(page.$.toast.open);
+
+    toggle.click();
+    assertTrue(page.$.toast.open);
+    const restartButton = page.$.toast.querySelector('cr-button');
+    assertTrue(!!restartButton);
+
+    restartButton.click();
+    return lifetimeBrowserProxy.whenCalled('restart');
+  });
+});
diff --git a/chrome/test/data/webui/settings/all_sites_test.ts b/chrome/test/data/webui/settings/all_sites_test.ts
index a96a8bb..e0d3bf2 100644
--- a/chrome/test/data/webui/settings/all_sites_test.ts
+++ b/chrome/test/data/webui/settings/all_sites_test.ts
@@ -398,7 +398,7 @@
   test('clear data "no sites" string', async function() {
     testElement.siteGroupMap.set(
         TEST_MULTIPLE_SITE_GROUP.groupingKey,
-        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)));
+        structuredClone(TEST_MULTIPLE_SITE_GROUP));
     const googleSiteGroup = createSiteGroup('google.com', 'google.com', [
       'https://www.google.com',
       'https://docs.google.com',
@@ -619,7 +619,7 @@
   test('cancelling the confirm dialog on clear all data works', function() {
     testElement.siteGroupMap.set(
         TEST_MULTIPLE_SITE_GROUP.groupingKey,
-        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)));
+        structuredClone(TEST_MULTIPLE_SITE_GROUP));
     testElement.forceListUpdateForTesting();
     clearDataViaClearAllButton('cancel-button');
   });
@@ -629,7 +629,7 @@
     // Clone this object to avoid propagating changes made in this test.
     testElement.siteGroupMap.set(
         TEST_MULTIPLE_SITE_GROUP.groupingKey,
-        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)));
+        structuredClone(TEST_MULTIPLE_SITE_GROUP));
     const googleSiteGroup = createSiteGroup('google.com', 'google.com', [
       'https://www.google.com',
       'https://docs.google.com',
@@ -652,10 +652,10 @@
       async function() {
         // Test when there is one origin has permissions settings.
         // Clone this object to avoid propagating changes made in this test.
-        const siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-        siteGroup.origins[0].hasPermissionSettings = true;
+        const siteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
+        siteGroup.origins[0]!.hasPermissionSettings = true;
         testElement.siteGroupMap.set(
-            siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+            siteGroup.groupingKey, structuredClone(siteGroup));
         const googleSiteGroup = createSiteGroup('google.com', 'google.com', [
           'https://www.google.com',
           'https://docs.google.com',
@@ -716,7 +716,7 @@
   test('remove site group', function() {
     testElement.siteGroupMap.set(
         TEST_MULTIPLE_SITE_GROUP.groupingKey,
-        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)));
+        structuredClone(TEST_MULTIPLE_SITE_GROUP));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -731,13 +731,13 @@
   });
 
   test('remove origin', async function() {
-    const siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    siteGroup.origins[0].numCookies = 1;
-    siteGroup.origins[1].numCookies = 2;
-    siteGroup.origins[2].numCookies = 3;
+    const siteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
+    siteGroup.origins[0]!.numCookies = 1;
+    siteGroup.origins[1]!.numCookies = 2;
+    siteGroup.origins[2]!.numCookies = 3;
     siteGroup.numCookies = 6;
     testElement.siteGroupMap.set(
-        siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+        siteGroup.groupingKey, structuredClone(siteGroup));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -745,13 +745,13 @@
     confirmDialog();
 
     assertEquals(
-        siteGroup.origins[0].origin,
+        siteGroup.origins[0]!.origin,
         await browserProxy.whenCalled(
             'clearUnpartitionedOriginDataAndCookies'));
 
     const [origin, types, setting] =
         await browserProxy.whenCalled('setOriginPermissions');
-    assertEquals(origin, siteGroup.origins[0].origin);
+    assertEquals(origin, siteGroup.origins[0]!.origin);
     assertEquals(types, null);  // Null affects all content types.
     assertEquals(setting, ContentSetting.DEFAULT);
 
@@ -762,15 +762,15 @@
   });
 
   test('remove partitioned origin', async function() {
-    const siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    siteGroup.origins[0].isPartitioned = true;
-    siteGroup.origins[0].numCookies = 1;
-    siteGroup.origins[1].numCookies = 2;
-    siteGroup.origins[2].numCookies = 3;
+    const siteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
+    siteGroup.origins[0]!.isPartitioned = true;
+    siteGroup.origins[0]!.numCookies = 1;
+    siteGroup.origins[1]!.numCookies = 2;
+    siteGroup.origins[2]!.numCookies = 3;
     siteGroup.numCookies = 6;
 
     testElement.siteGroupMap.set(
-        siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+        siteGroup.groupingKey, structuredClone(siteGroup));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -789,7 +789,7 @@
     const [origin, groupingKey] =
         await browserProxy.whenCalled('clearPartitionedOriginDataAndCookies');
 
-    assertEquals(siteGroup.origins[0].origin, origin);
+    assertEquals(siteGroup.origins[0]!.origin, origin);
     assertEquals(siteGroup.groupingKey, groupingKey);
     assertEquals(
         1, browserProxy.getCallCount('clearPartitionedOriginDataAndCookies'));
@@ -800,7 +800,7 @@
   test('cancel remove site group', function() {
     testElement.siteGroupMap.set(
         TEST_MULTIPLE_SITE_GROUP.groupingKey,
-        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)));
+        structuredClone(TEST_MULTIPLE_SITE_GROUP));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -813,13 +813,13 @@
   });
 
   test('cancel remove origin', function() {
-    const siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    siteGroup.origins[0].numCookies = 1;
-    siteGroup.origins[1].numCookies = 2;
-    siteGroup.origins[2].numCookies = 3;
+    const siteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
+    siteGroup.origins[0]!.numCookies = 1;
+    siteGroup.origins[1]!.numCookies = 2;
+    siteGroup.origins[2]!.numCookies = 3;
     siteGroup.numCookies = 6;
     testElement.siteGroupMap.set(
-        siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+        siteGroup.groupingKey, structuredClone(siteGroup));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -833,10 +833,10 @@
   });
 
   test('permissions bullet point visbility', function() {
-    const siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    siteGroup.origins[0].hasPermissionSettings = true;
+    const siteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
+    siteGroup.origins[0]!.hasPermissionSettings = true;
     testElement.siteGroupMap.set(
-        siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+        siteGroup.groupingKey, structuredClone(siteGroup));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -850,9 +850,9 @@
     assertTrue(isChildVisible(testElement, '#permissionsBulletPoint'));
     cancelDialog();
 
-    siteGroup.origins[0].hasPermissionSettings = false;
+    siteGroup.origins[0]!.hasPermissionSettings = false;
     testElement.siteGroupMap.set(
-        siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+        siteGroup.groupingKey, structuredClone(siteGroup));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -869,9 +869,9 @@
 
   test('dynamic strings', async function() {
     // Single origin, no apps.
-    const siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+    const siteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
     testElement.siteGroupMap.set(
-        siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+        siteGroup.groupingKey, structuredClone(siteGroup));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -901,9 +901,9 @@
     cancelDialog();
 
     // Single origin with app.
-    siteGroup.origins[0].isInstalled = true;
+    siteGroup.origins[0]!.isInstalled = true;
     testElement.siteGroupMap.set(
-        siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+        siteGroup.groupingKey, structuredClone(siteGroup));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -934,9 +934,9 @@
     cancelDialog();
 
     // Site group, multiple sites, multiple apps.
-    siteGroup.origins[1].isInstalled = true;
+    siteGroup.origins[1]!.isInstalled = true;
     testElement.siteGroupMap.set(
-        siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+        siteGroup.groupingKey, structuredClone(siteGroup));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -953,11 +953,10 @@
     cancelDialog();
 
     // Site group, single origin, no app.
-    const singleOriginSiteGroup =
-        JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
+    const singleOriginSiteGroup = structuredClone(TEST_SINGLE_SITE_GROUP);
     testElement.siteGroupMap.set(
         singleOriginSiteGroup.groupingKey,
-        JSON.parse(JSON.stringify(singleOriginSiteGroup)));
+        structuredClone(singleOriginSiteGroup));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -974,10 +973,10 @@
     cancelDialog();
 
     // Site group, single origin, one app.
-    singleOriginSiteGroup.origins[0].isInstalled = true;
+    singleOriginSiteGroup.origins[0]!.isInstalled = true;
     testElement.siteGroupMap.set(
         singleOriginSiteGroup.groupingKey,
-        JSON.parse(JSON.stringify(singleOriginSiteGroup)));
+        structuredClone(singleOriginSiteGroup));
     testElement.forceListUpdateForTesting();
     flush();
 
@@ -1161,10 +1160,10 @@
   }
 
   test('remove site via overflow menu', async function() {
-    const siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+    const siteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
     siteGroup.fpsOwner = 'google.com';
     testElement.siteGroupMap.set(
-        siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+        siteGroup.groupingKey, structuredClone(siteGroup));
     testElement.forceListUpdateForTesting();
     assertEquals(testElement.$.allSitesList.items!.length, 1);
     removeSiteViaOverflowMenu('action-button');
@@ -1177,10 +1176,10 @@
 
   test(
       'cancelling the confirm dialog on removing site works', async function() {
-        const siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+        const siteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
         siteGroup.fpsOwner = 'google.com';
         testElement.siteGroupMap.set(
-            siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+            siteGroup.groupingKey, structuredClone(siteGroup));
         testElement.forceListUpdateForTesting();
         removeSiteViaOverflowMenu('cancel-button');
       });
@@ -1188,7 +1187,7 @@
   test('click and remove site entry with remove button', async function() {
     testElement.siteGroupMap.set(
         TEST_MULTIPLE_SITE_GROUP.groupingKey,
-        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)));
+        structuredClone(TEST_MULTIPLE_SITE_GROUP));
     testElement.forceListUpdateForTesting();
     flush();
     removeFirstSiteGroup();
@@ -1204,7 +1203,7 @@
       async function() {
         testElement.siteGroupMap.set(
             TEST_MULTIPLE_SITE_GROUP.groupingKey,
-            JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)));
+            structuredClone(TEST_MULTIPLE_SITE_GROUP));
         testElement.forceListUpdateForTesting();
         flush();
         removeFirstSiteGroup();
@@ -1214,7 +1213,7 @@
   test('filter sites by first party set owner', async function() {
     TEST_SITE_GROUPS.forEach(siteGroup => {
       testElement.siteGroupMap.set(
-          siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+          siteGroup.groupingKey, structuredClone(siteGroup));
     });
     testElement.forceListUpdateForTesting();
     flush();
@@ -1270,7 +1269,7 @@
       async function() {
         TEST_FPS_SITE_GROUPS.forEach(siteGroup => {
           testElement.siteGroupMap.set(
-              siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+              siteGroup.groupingKey, structuredClone(siteGroup));
         });
         testElement.forceListUpdateForTesting();
         flush();
@@ -1298,7 +1297,7 @@
       async function() {
         TEST_FPS_SITE_GROUPS.forEach(siteGroup => {
           testElement.siteGroupMap.set(
-              siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+              siteGroup.groupingKey, structuredClone(siteGroup));
         });
         testElement.forceListUpdateForTesting();
         flush();
@@ -1364,7 +1363,7 @@
       function() {
         TEST_SITE_GROUPS.forEach(siteGroup => {
           testElement.siteGroupMap.set(
-              siteGroup.groupingKey, JSON.parse(JSON.stringify(siteGroup)));
+              siteGroup.groupingKey, structuredClone(siteGroup));
         });
         testElement.forceListUpdateForTesting();
         flush();
diff --git a/chrome/test/data/webui/settings/basic_page_test.ts b/chrome/test/data/webui/settings/basic_page_test.ts
index 2de0cb4..233bb69 100644
--- a/chrome/test/data/webui/settings/basic_page_test.ts
+++ b/chrome/test/data/webui/settings/basic_page_test.ts
@@ -637,3 +637,30 @@
         'Safety Hub section should not be visible with default visibility');
   });
 });
+
+suite('ExperimentalAdvanced', () => {
+  let page: SettingsBasicPageElement;
+
+  function createBasicPage() {
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
+    page = document.createElement('settings-basic-page');
+    document.body.appendChild(page);
+    flush();
+  }
+
+  test('sectionNotVisible', function() {
+    loadTimeData.overrideValues({showAdvancedFeaturesMainControl: false});
+    createBasicPage();
+    const sectionElement =
+        page.shadowRoot!.querySelector('settings-section[section=ai]');
+    assertFalse(!!sectionElement);
+  });
+
+  test('sectionVisible', function() {
+    loadTimeData.overrideValues({showAdvancedFeaturesMainControl: true});
+    createBasicPage();
+    const sectionElement =
+        page.shadowRoot!.querySelector('settings-section[section=ai]');
+    assertTrue(!!sectionElement);
+  });
+});
diff --git a/chrome/test/data/webui/settings/chromeos/date_time_page/date_time_page_test.ts b/chrome/test/data/webui/settings/chromeos/date_time_page/date_time_page_test.ts
index f5e9df1e..e42f1a9 100644
--- a/chrome/test/data/webui/settings/chromeos/date_time_page/date_time_page_test.ts
+++ b/chrome/test/data/webui/settings/chromeos/date_time_page/date_time_page_test.ts
@@ -5,7 +5,7 @@
 import 'chrome://os-settings/lazy_load.js';
 
 import {DateTimeSettingsCardElement, SettingsDateTimePageElement, TimeZoneAutoDetectMethod, TimeZoneBrowserProxyImpl, TimezoneSubpageElement} from 'chrome://os-settings/lazy_load.js';
-import {ControlledRadioButtonElement, CrSettingsPrefs, Router, routes, SettingsDropdownMenuElement, SettingsToggleButtonElement} from 'chrome://os-settings/os_settings.js';
+import {ControlledRadioButtonElement, CrSettingsPrefs, PrefsState, Router, routes, SettingsDropdownMenuElement, SettingsToggleButtonElement} from 'chrome://os-settings/os_settings.js';
 import {webUIListenerCallback} from 'chrome://resources/js/cr.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -68,9 +68,8 @@
 }
 
 function updatePrefsWithPolicy(
-    prefs: {[key: string]: unknown}, managed: boolean,
-    valueFromPolicy: boolean): Object {
-  const prefsCopy = JSON.parse(JSON.stringify(prefs));
+    prefs: PrefsState, managed: boolean, valueFromPolicy: boolean): Object {
+  const prefsCopy = structuredClone(prefs) as any;
   if (managed) {
     prefsCopy.generated.resolve_timezone_by_geolocation_method_short
         .controlledBy = chrome.settingsPrivate.ControlledBy.USER_POLICY;
diff --git a/chrome/test/data/webui/settings/chromeos/internet_page_tests.js b/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
index 4035de82..70ed737 100644
--- a/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
@@ -5,7 +5,7 @@
 import 'chrome://os-settings/os_settings.js';
 import 'chrome://os-settings/lazy_load.js';
 
-import {Router, routes} from 'chrome://os-settings/os_settings.js';
+import {Router, routes, settingMojom} from 'chrome://os-settings/os_settings.js';
 import {CellularSetupPageName} from 'chrome://resources/ash/common/cellular_setup/cellular_types.js';
 import {setESimManagerRemoteForTesting} from 'chrome://resources/ash/common/cellular_setup/mojo_interface_provider.js';
 import {MojoConnectivityProvider} from 'chrome://resources/ash/common/connectivity/mojo_connectivity_provider.js';
@@ -306,7 +306,7 @@
       mojoApi_.setNetworkTypeEnabledState(NetworkType.kWiFi, false);
 
       const params = new URLSearchParams();
-      params.append('settingId', '4');
+      params.append('settingId', settingMojom.Setting.kWifiOnOff.toString());
       Router.getInstance().navigateTo(routes.INTERNET, params);
 
       await flushAsync();
@@ -321,6 +321,34 @@
           'Toggle WiFi should be focused for settingId=4.');
     });
 
+    test('Deep link to + New APN Button', async () => {
+      loadTimeData.overrideValues({isApnRevampEnabled: true});
+      await init();
+
+      const cellularNetwork = OncMojo.getDefaultManagedProperties(
+          NetworkType.kCellular, 'cellular1', 'name1');
+      cellularNetwork.typeProperties.cellular.eid = 'eid';
+      mojoApi_.setManagedPropertiesForTest(cellularNetwork);
+
+      const params = new URLSearchParams();
+      params.append(
+          'settingId', settingMojom.Setting.kCellularAddApn.toString());
+      params.append('guid', cellularNetwork.guid);
+
+      Router.getInstance().navigateTo(routes.APN, params);
+      await flushAsync();
+
+      const deepLinkElement =
+          internetPage.shadowRoot.querySelector('#createCustomApnButton');
+      assertTrue(!!deepLinkElement);
+
+      await waitAfterNextRender(deepLinkElement);
+      assertEquals(
+          deepLinkElement, getDeepActiveElement(),
+          `+ New APN Button be focused for settingId=${
+              settingMojom.Setting.kCellularAddApn.toString()}.`);
+    });
+
     suite('VPN', function() {
       test('VpnProviders', async function() {
         await init();
@@ -522,7 +550,7 @@
       mojoApi_.setNetworkTypeEnabledState(NetworkType.kCellular, false);
 
       const params = new URLSearchParams();
-      params.append('settingId', '13');
+      params.append('settingId', settingMojom.Setting.kMobileOnOff.toString());
       Router.getInstance().navigateTo(routes.INTERNET, params);
 
       await flushAsync();
diff --git a/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_page_test.ts b/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_page_test.ts
index db3e543..9b15c29 100644
--- a/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_page_test.ts
+++ b/chrome/test/data/webui/settings/chromeos/os_printing_page/cups_printer_page_test.ts
@@ -30,12 +30,13 @@
     page = document.createElement('settings-cups-printers');
     document.body.appendChild(page);
     assertTrue(!!page);
+    await flushTasks();
 
     // Simulate internet connection.
     wifi = OncMojo.getDefaultNetworkState(NetworkType.kWiFi, 'wifi');
     wifi.connectionState = ConnectionStateType.kOnline;
-
-    await flushTasks();
+    page.onActiveNetworksChanged([wifi]);
+    return Promise.resolve();
   }
 
   setup(async () => {
@@ -83,7 +84,7 @@
   });
 
   // Verify the Nearby printers section can be properly opened and closed.
-  test.skip('CollapsibleNearbyPrinterSection', () => {
+  test('CollapsibleNearbyPrinterSection', () => {
     // The Add printer section above the Nearby printers section should be
     // hidden.
     assertFalse(
@@ -127,7 +128,7 @@
 
   // Verify the Nearby printers section starts open when there are no saved
   // printers or open when there's more than one saved printer.
-  test.skip('CollapsibleNearbyPrinterSectionSavedPrinters', async () => {
+  test('CollapsibleNearbyPrinterSectionSavedPrinters', async () => {
     // Simulate no saved printers and expect the section to be open.
     cupsPrintersBrowserProxy.printerList = {printerList: []};
     resetPage();
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_menu/os_settings_menu_revamp_test.ts b/chrome/test/data/webui/settings/chromeos/os_settings_menu/os_settings_menu_revamp_test.ts
index 7b9d96f..18be7647 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_menu/os_settings_menu_revamp_test.ts
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_menu/os_settings_menu_revamp_test.ts
@@ -277,6 +277,18 @@
     });
   });
 
+  suite('A11y menu item', () => {
+    test('Description text', async () => {
+      await createMenu();
+
+      const a11yMenuItem =
+          queryMenuItemByPath(`/${routesMojom.ACCESSIBILITY_SECTION_PATH}`);
+      assertTrue(!!a11yMenuItem);
+
+      assertEquals('Screen reader, magnification', a11yMenuItem.sublabel);
+    });
+  });
+
   suite('Bluetooth menu item', () => {
     let bluetoothConfig: FakeBluetoothConfig;
     const bluetoothMouse = createDefaultBluetoothDevice(
diff --git a/chrome/test/data/webui/settings/settings_browsertest.cc b/chrome/test/data/webui/settings/settings_browsertest.cc
index 0142e5c..629d295 100644
--- a/chrome/test/data/webui/settings/settings_browsertest.cc
+++ b/chrome/test/data/webui/settings/settings_browsertest.cc
@@ -129,6 +129,10 @@
 }
 #endif
 
+IN_PROC_BROWSER_TEST_F(SettingsTest, ExperimentalAdvancedPage) {
+  RunTest("settings/ai_page_test.js", "mocha.run()");
+}
+
 IN_PROC_BROWSER_TEST_F(SettingsTest, ExtensionControlledIndicator) {
   RunTest("settings/extension_controlled_indicator_test.js", "mocha.run()");
 }
@@ -517,6 +521,11 @@
   RunTest("settings/basic_page_test.js", "runMochaSuite('SafetyHubDisabled')");
 }
 
+IN_PROC_BROWSER_TEST_F(SettingsBasicPageTest, ExperimentalAdvanced) {
+  RunTest("settings/basic_page_test.js",
+          "runMochaSuite('ExperimentalAdvanced')");
+}
+
 using SettingsClearBrowsingDataTest = SettingsBrowserTest;
 
 // TODO(crbug.com/1107652): Flaky on Mac.
diff --git a/chrome/test/data/webui/settings/settings_menu_test.ts b/chrome/test/data/webui/settings/settings_menu_test.ts
index 47a1b3a..206c433 100644
--- a/chrome/test/data/webui/settings/settings_menu_test.ts
+++ b/chrome/test/data/webui/settings/settings_menu_test.ts
@@ -6,14 +6,10 @@
 
 // clang-format off
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {pageVisibility, Router, SettingsMenuElement, SettingsRoutes} from 'chrome://settings/settings.js';
-// <if expr="_google_chrome">
-import {buildRouter, loadTimeData} from 'chrome://settings/settings.js';
-// </if>
-import {assertEquals, assertFalse} from 'chrome://webui-test/chai_assert.js';
-// <if expr="_google_chrome">
-import {assertTrue} from 'chrome://webui-test/chai_assert.js';
-// </if>
+import {buildRouter, loadTimeData, pageVisibility, Router, SettingsMenuElement, SettingsRoutes} from 'chrome://settings/settings.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {isVisible} from 'chrome://webui-test/test_util.js';
+import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 
 // clang-format on
 
@@ -100,6 +96,33 @@
   });
   // </if>
 
+  test('noExperimental', async function() {
+    loadTimeData.overrideValues({showAdvancedFeaturesMainControl: false});
+    Router.resetInstanceForTesting(buildRouter());
+    createSettingsMenu();
+    await flushTasks();
+
+    const entry = settingsMenu.shadowRoot!.querySelector('a[href=\'/ai\']');
+    assertTrue(!!entry);
+    assertFalse(isVisible(entry));
+  });
+
+  test('navigateToExperimental', async function() {
+    loadTimeData.overrideValues({showAdvancedFeaturesMainControl: true});
+    Router.resetInstanceForTesting(buildRouter());
+    createSettingsMenu();
+    Router.getInstance().navigateTo(routes.AI);
+    await flushTasks();
+
+    const entry = settingsMenu.shadowRoot!.querySelector('a[href=\'/ai\']');
+    assertTrue(!!entry);
+    assertTrue(isVisible(entry));
+
+    const selector = settingsMenu.$.menu;
+    const path = new window.URL(selector.selected.toString()).pathname;
+    assertEquals('/ai', path);
+  });
+
   test('pageVisibility', function() {
     function assertPagesHidden(expectedHidden: boolean) {
       const ids = [
diff --git a/chrome/test/data/webui/settings/site_entry_test.ts b/chrome/test/data/webui/settings/site_entry_test.ts
index 3283ddcd..607dba6 100644
--- a/chrome/test/data/webui/settings/site_entry_test.ts
+++ b/chrome/test/data/webui/settings/site_entry_test.ts
@@ -134,16 +134,14 @@
       'moving from grouped to ungrouped does not get stuck in opened state',
       function() {
         // Clone this object to avoid propagating changes made in this test.
-        testElement.siteGroup =
-            JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+        testElement.siteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
         flush();
         testElement.$.toggleButton.click();
         assertTrue(testElement.$.originList.get().opened);
 
         // Remove all origins except one, then make sure it's not still
         // expanded.
-        const siteGroupUpdated =
-            JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+        const siteGroupUpdated = structuredClone(TEST_MULTIPLE_SITE_GROUP);
         siteGroupUpdated.origins.splice(1);
         testElement.siteGroup = siteGroupUpdated;
         assertEquals(1, testElement.siteGroup.origins.length);
@@ -156,7 +154,7 @@
     const cookiesLabel = testElement.$.cookies;
     assertTrue(cookiesLabel.hidden);
     // When the number of cookies is more than zero, the label appears.
-    const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+    const testSiteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
     const numCookies = 3;
     testSiteGroup.numCookies = numCookies;
 
@@ -176,7 +174,7 @@
     assertTrue(cookiesLabel.hidden);
 
 
-    const testSiteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
+    const testSiteGroup = structuredClone(TEST_SINGLE_SITE_GROUP);
     const numCookies = 3;
 
     testSiteGroup.numCookies = numCookies;
@@ -192,13 +190,13 @@
 
   test('data usage shown correctly for grouped entries', async function() {
     // Clone this object to avoid propagating changes made in this test.
-    const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+    const testSiteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
     const numBytes1 = 74622;
     const numBytes2 = 1274;
     const numBytes3 = 0;
-    testSiteGroup.origins[0].usage = numBytes1;
-    testSiteGroup.origins[1].usage = numBytes2;
-    testSiteGroup.origins[2].usage = numBytes3;
+    testSiteGroup.origins[0]!.usage = numBytes1;
+    testSiteGroup.origins[1]!.usage = numBytes2;
+    testSiteGroup.origins[2]!.usage = numBytes3;
     testElement.siteGroup = testSiteGroup;
     flush();
     const args = await browserProxy.whenCalled('getFormattedBytes');
@@ -213,9 +211,9 @@
 
   test('data usage shown correctly for ungrouped entries', async function() {
     // Clone this object to avoid propagating changes made in this test.
-    const testSiteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
+    const testSiteGroup = structuredClone(TEST_SINGLE_SITE_GROUP);
     const numBytes = 74622;
-    testSiteGroup.origins[0].usage = numBytes;
+    testSiteGroup.origins[0]!.usage = numBytes;
     testElement.siteGroup = testSiteGroup;
     flush();
     const args = await browserProxy.whenCalled('getFormattedBytes');
@@ -231,14 +229,13 @@
       'large number data usage shown correctly for grouped entries',
       async function() {
         // Clone this object to avoid propagating changes made in this test.
-        const testSiteGroup =
-            JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+        const testSiteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
         const numBytes1 = 2000000000;
         const numBytes2 = 10000000000;
         const numBytes3 = 7856;
-        testSiteGroup.origins[0].usage = numBytes1;
-        testSiteGroup.origins[1].usage = numBytes2;
-        testSiteGroup.origins[2].usage = numBytes3;
+        testSiteGroup.origins[0]!.usage = numBytes1;
+        testSiteGroup.origins[1]!.usage = numBytes2;
+        testSiteGroup.origins[2]!.usage = numBytes3;
         testElement.siteGroup = testSiteGroup;
         flush();
         const args = await browserProxy.whenCalled('getFormattedBytes');
@@ -253,10 +250,10 @@
 
   test('favicon with www.etld+1 chosen for site group', function() {
     // Clone this object to avoid propagating changes made in this test.
-    const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    testSiteGroup.origins[0].usage = 0;
-    testSiteGroup.origins[1].usage = 1274;
-    testSiteGroup.origins[2].usage = 74622;
+    const testSiteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
+    testSiteGroup.origins[0]!.usage = 0;
+    testSiteGroup.origins[1]!.usage = 1274;
+    testSiteGroup.origins[2]!.usage = 74622;
     testElement.siteGroup = testSiteGroup;
     flush();
     assertEquals(
@@ -266,11 +263,11 @@
 
   test('favicon with largest storage chosen for site group', function() {
     // Clone this object to avoid propagating changes made in this test.
-    const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    testSiteGroup.origins[0].usage = 0;
-    testSiteGroup.origins[1].usage = 1274;
-    testSiteGroup.origins[2].usage = 74622;
-    testSiteGroup.origins[1].origin = 'https://abc.example.com';
+    const testSiteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
+    testSiteGroup.origins[0]!.usage = 0;
+    testSiteGroup.origins[1]!.usage = 1274;
+    testSiteGroup.origins[2]!.usage = 74622;
+    testSiteGroup.origins[1]!.origin = 'https://abc.example.com';
     testElement.siteGroup = testSiteGroup;
     flush();
     assertEquals(
@@ -280,14 +277,14 @@
 
   test('favicon with largest cookies number chosen for site group', function() {
     // Clone this object to avoid propagating changes made in this test.
-    const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    testSiteGroup.origins[0].usage = 0;
-    testSiteGroup.origins[1].usage = 1274;
-    testSiteGroup.origins[2].usage = 1274;
-    testSiteGroup.origins[0].numCookies = 10;
-    testSiteGroup.origins[1].numCookies = 3;
-    testSiteGroup.origins[2].numCookies = 1;
-    testSiteGroup.origins[1].origin = 'https://abc.example.com';
+    const testSiteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
+    testSiteGroup.origins[0]!.usage = 0;
+    testSiteGroup.origins[1]!.usage = 1274;
+    testSiteGroup.origins[2]!.usage = 1274;
+    testSiteGroup.origins[0]!.numCookies = 10;
+    testSiteGroup.origins[1]!.numCookies = 3;
+    testSiteGroup.origins[2]!.numCookies = 1;
+    testSiteGroup.origins[1]!.origin = 'https://abc.example.com';
     testElement.siteGroup = testSiteGroup;
     flush();
     assertEquals(
@@ -297,16 +294,16 @@
 
   test('can be sorted by most visited', function() {
     // Clone this object to avoid propagating changes made in this test.
-    const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    testSiteGroup.origins[0].engagement = 20;
-    testSiteGroup.origins[1].engagement = 30;
-    testSiteGroup.origins[2].engagement = 10;
-    testSiteGroup.origins[0].usage = 0;
-    testSiteGroup.origins[1].usage = 1274;
-    testSiteGroup.origins[2].usage = 1274;
-    testSiteGroup.origins[0].numCookies = 10;
-    testSiteGroup.origins[1].numCookies = 3;
-    testSiteGroup.origins[2].numCookies = 1;
+    const testSiteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
+    testSiteGroup.origins[0]!.engagement = 20;
+    testSiteGroup.origins[1]!.engagement = 30;
+    testSiteGroup.origins[2]!.engagement = 10;
+    testSiteGroup.origins[0]!.usage = 0;
+    testSiteGroup.origins[1]!.usage = 1274;
+    testSiteGroup.origins[2]!.usage = 1274;
+    testSiteGroup.origins[0]!.numCookies = 10;
+    testSiteGroup.origins[1]!.numCookies = 3;
+    testSiteGroup.origins[2]!.numCookies = 1;
     testElement.sortMethod = SortMethod.MOST_VISITED;
     testElement.siteGroup = testSiteGroup;
     flush();
@@ -330,16 +327,16 @@
 
   test('can be sorted by storage', function() {
     // Clone this object to avoid propagating changes made in this test.
-    const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    testSiteGroup.origins[0].engagement = 20;
-    testSiteGroup.origins[1].engagement = 30;
-    testSiteGroup.origins[2].engagement = 10;
-    testSiteGroup.origins[0].usage = 0;
-    testSiteGroup.origins[1].usage = 1274;
-    testSiteGroup.origins[2].usage = 1274;
-    testSiteGroup.origins[0].numCookies = 10;
-    testSiteGroup.origins[1].numCookies = 3;
-    testSiteGroup.origins[2].numCookies = 1;
+    const testSiteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
+    testSiteGroup.origins[0]!.engagement = 20;
+    testSiteGroup.origins[1]!.engagement = 30;
+    testSiteGroup.origins[2]!.engagement = 10;
+    testSiteGroup.origins[0]!.usage = 0;
+    testSiteGroup.origins[1]!.usage = 1274;
+    testSiteGroup.origins[2]!.usage = 1274;
+    testSiteGroup.origins[0]!.numCookies = 10;
+    testSiteGroup.origins[1]!.numCookies = 3;
+    testSiteGroup.origins[2]!.numCookies = 1;
     testElement.sortMethod = SortMethod.STORAGE;
     testElement.siteGroup = testSiteGroup;
     flush();
@@ -363,16 +360,16 @@
 
   test('can be sorted by name', function() {
     // Clone this object to avoid propagating changes made in this test.
-    const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    testSiteGroup.origins[0].engagement = 20;
-    testSiteGroup.origins[1].engagement = 30;
-    testSiteGroup.origins[2].engagement = 10;
-    testSiteGroup.origins[0].usage = 0;
-    testSiteGroup.origins[1].usage = 1274;
-    testSiteGroup.origins[2].usage = 1274;
-    testSiteGroup.origins[0].numCookies = 10;
-    testSiteGroup.origins[1].numCookies = 3;
-    testSiteGroup.origins[2].numCookies = 1;
+    const testSiteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
+    testSiteGroup.origins[0]!.engagement = 20;
+    testSiteGroup.origins[1]!.engagement = 30;
+    testSiteGroup.origins[2]!.engagement = 10;
+    testSiteGroup.origins[0]!.usage = 0;
+    testSiteGroup.origins[1]!.usage = 1274;
+    testSiteGroup.origins[2]!.usage = 1274;
+    testSiteGroup.origins[0]!.numCookies = 10;
+    testSiteGroup.origins[1]!.numCookies = 3;
+    testSiteGroup.origins[2]!.numCookies = 1;
     testElement.sortMethod = SortMethod.NAME;
     testElement.siteGroup = testSiteGroup;
     flush();
@@ -395,8 +392,7 @@
   });
 
   test('remove site fires correct event for individual site', async function() {
-    testElement.siteGroup =
-        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+    testElement.siteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
     flush();
 
     const collapseChild = testElement.$.originList.get();
@@ -417,8 +413,7 @@
   });
 
   test('remove site fires correct event for site group', async function() {
-    testElement.siteGroup =
-        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+    testElement.siteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
     flush();
 
     const siteRemoved = eventToPromise('remove-site', testElement);
@@ -435,7 +430,7 @@
 
   test('partitioned entry interaction', async function() {
     // Clone this object to avoid propagating changes made in this test.
-    const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+    const testSiteGroup = structuredClone(TEST_MULTIPLE_SITE_GROUP);
 
     // Add a partitioned entry for an unrelated origin.
     testSiteGroup.origins.push(
@@ -473,8 +468,8 @@
   test('partitioned entry prevents collapse', function() {
     // If a siteGroup has a partitioned entry, even if it is the only entry,
     // it should keep the site entry as a top level + collapse list.
-    const testSingleSite = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
-    testSingleSite.origins[0].isPartitioned = true;
+    const testSingleSite = structuredClone(TEST_SINGLE_SITE_GROUP);
+    testSingleSite.origins[0]!.isPartitioned = true;
 
     testElement.siteGroup = testSingleSite;
     flush();
@@ -493,7 +488,7 @@
   test('unpartitioned entry remains collapsed', async function() {
     // Check that a single origin containing unpartitioned storage only is
     // correctly collapsed.
-    testElement.siteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
+    testElement.siteGroup = structuredClone(TEST_SINGLE_SITE_GROUP);
     flush();
     const collapseChild = testElement.$.originList.get();
 
@@ -513,7 +508,7 @@
 
   test('first party set information showed when available', async function() {
     // Set unowned site group.
-    testElement.siteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
+    testElement.siteGroup = structuredClone(TEST_SINGLE_SITE_GROUP);
     flush();
 
     const fpsMembershipLabel = testElement.$.fpsMembership;
@@ -521,7 +516,7 @@
     assertTrue(fpsMembershipLabel.hidden);
 
     // Update first party set information and set siteGroup
-    const fooSiteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
+    const fooSiteGroup = structuredClone(TEST_SINGLE_SITE_GROUP);
     fooSiteGroup.fpsOwner = 'foo.com';
     fooSiteGroup.fpsNumMembers = 1;
     testElement.siteGroup = fooSiteGroup;
@@ -536,7 +531,7 @@
 
   test('first party set policy shown when managed key is true', function() {
     // Set site group with first party set information.
-    const fooSiteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
+    const fooSiteGroup = structuredClone(TEST_SINGLE_SITE_GROUP);
     fooSiteGroup.fpsOwner = 'foo.com';
     fooSiteGroup.fpsNumMembers = 1;
     fooSiteGroup.fpsEnterpriseManaged = true;
@@ -551,7 +546,7 @@
   test(
       'first party set policy undefined when managed key is false', function() {
         // Set site group with first party set information.
-        const fooSiteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
+        const fooSiteGroup = structuredClone(TEST_SINGLE_SITE_GROUP);
         fooSiteGroup.fpsOwner = 'foo.com';
         fooSiteGroup.fpsNumMembers = 1;
         fooSiteGroup.fpsEnterpriseManaged = false;
@@ -565,7 +560,7 @@
 
   test('first party set more actions aria-label set correctly', function() {
     // Set site group with first party set information.
-    const fooSiteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
+    const fooSiteGroup = structuredClone(TEST_SINGLE_SITE_GROUP);
     fooSiteGroup.fpsOwner = 'foo.com';
     fooSiteGroup.fpsNumMembers = 1;
     fooSiteGroup.fpsEnterpriseManaged = false;
@@ -583,7 +578,7 @@
       'first party set more actions menu removed when filtered by fps owner',
       function() {
         // Set site group with first party set information.
-        const fooSiteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
+        const fooSiteGroup = structuredClone(TEST_SINGLE_SITE_GROUP);
         fooSiteGroup.fpsOwner = 'foo.com';
         fooSiteGroup.fpsNumMembers = 1;
         fooSiteGroup.fpsEnterpriseManaged = false;
@@ -607,10 +602,9 @@
       });
 
   test('extension site group is shown correctly', async function() {
-    const extensionSiteGroup =
-        JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP));
+    const extensionSiteGroup = structuredClone(TEST_SINGLE_SITE_GROUP);
     extensionSiteGroup.displayName = 'Test Extension';
-    extensionSiteGroup.origins[0].origin =
+    extensionSiteGroup.origins[0]!.origin =
         'chrome-extension://mhabknllooicelmdboebjilbohdbihln';
     testElement.siteGroup = extensionSiteGroup;
     flush();
diff --git a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.ts b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.ts
index aa42cb8..d68af14 100644
--- a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.ts
+++ b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.ts
@@ -368,26 +368,26 @@
     // Create a deep copy of the pref so that the chooser-exception-list element
     // is able update the UI appropriately when incognito mode is toggled.
     const pref = /** @type {!Array<!RawChooserException>} */ (
-        JSON.parse(JSON.stringify(this.prefs_.chooserExceptions[setting!])));
+        structuredClone(this.prefs_.chooserExceptions[setting!]));
     assert(pref !== undefined, 'Pref is missing for ' + chooserType);
 
     if (this.hasIncognito_) {
       for (let i = 0; i < pref.length; ++i) {
         const incognitoElements = [];
-        for (let j = 0; j < pref[i].sites.length; ++j) {
+        for (let j = 0; j < pref[i]!.sites.length; ++j) {
           // Skip preferences that are not controlled by policy since opening an
           // incognito session does not automatically grant permission to
           // chooser exceptions that have been granted in the main session.
-          if (pref[i].sites[j].source !== SiteSettingSource.POLICY) {
+          if (pref[i]!.sites[j]!.source !== SiteSettingSource.POLICY) {
             continue;
           }
 
           // Copy |sites[i]| to avoid changing the original |sites[i]|.
-          const incognitoSite = Object.assign({}, pref[i].sites[j]);
+          const incognitoSite = Object.assign({}, pref[i]!.sites[j]);
           incognitoElements.push(
               Object.assign(incognitoSite, {incognito: true}));
         }
-        pref[i].sites.push(...incognitoElements);
+        pref[i]!.sites.push(...incognitoElements);
       }
     }
 
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_test.ts
index 9ad656b..0db42fd 100644
--- a/chrome/test/data/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_test.ts
+++ b/chrome/test/data/webui/side_panel/customize_chrome/wallpaper_search/wallpaper_search_test.ts
@@ -440,6 +440,50 @@
   });
 
   suite('Error', () => {
+    test(
+        'shows error ui if no descriptors are returned by the backend',
+        async () => {
+          createWallpaperSearchElement(/*descriptors=*/ null);
+          await flushTasks();
+
+          wallpaperSearchElement.$.submitButton.click();
+          await waitAfterNextRender(wallpaperSearchElement);
+
+          assertNotStyle(
+              $$(wallpaperSearchElement, '#error')!, 'display', 'none');
+          assertStyle(
+              $$(wallpaperSearchElement, '#wallpaperSearch')!, 'display',
+              'none');
+        });
+
+    test('reattempts failed descriptor fetch', async () => {
+      createWallpaperSearchElement();
+      await flushTasks();
+
+      assertEquals(1, handler.getCallCount('getDescriptors'));
+      assertNotStyle($$(wallpaperSearchElement, '#error')!, 'display', 'none');
+      assertStyle(
+          $$(wallpaperSearchElement, '#wallpaperSearch')!, 'display', 'none');
+
+      handler.setResultFor('getDescriptors', Promise.resolve({
+        status: WallpaperSearchStatus.kOk,
+        descriptors: {
+          descriptorA: [{category: 'foo', labels: ['bar', 'baz']}],
+          descriptorB: [{label: 'foo', imagePath: 'bar.png'}],
+          descriptorC: ['foo', 'bar', 'baz'],
+        },
+      }));
+      await flushTasks();
+
+      $$<HTMLElement>(wallpaperSearchElement, '#errorCTA')!.click();
+      await waitAfterNextRender(wallpaperSearchElement);
+
+      assertEquals(2, handler.getCallCount('getDescriptors'));
+      assertStyle($$(wallpaperSearchElement, '#error')!, 'display', 'none');
+      assertNotStyle(
+          $$(wallpaperSearchElement, '#wallpaperSearch')!, 'display', 'none');
+    });
+
     test('shows search ui if there are no errors', async () => {
       handler.setResultFor(
           'getWallpaperSearchResults',
@@ -459,35 +503,26 @@
           $$(wallpaperSearchElement, '#wallpaperSearch')!, 'display', 'none');
     });
 
-    test(
-        'shows error ui if no descriptors are returned by the backend',
-        async () => {
-          createWallpaperSearchElement(/*descriptors=*/ null);
-          await flushTasks();
+    [WallpaperSearchStatus.kError, WallpaperSearchStatus.kRequestThrottled]
+        .forEach((status) => {
+          test(
+              `shows error ui if search fails with status of ${status}`,
+              async () => {
+                handler.setResultFor(
+                    'getWallpaperSearchResults',
+                    Promise.resolve({status: status, results: []}));
+                createWallpaperSearchElementWithDescriptors();
+                await flushTasks();
 
-          wallpaperSearchElement.$.submitButton.click();
-          await waitAfterNextRender(wallpaperSearchElement);
+                wallpaperSearchElement.$.submitButton.click();
+                await waitAfterNextRender(wallpaperSearchElement);
 
-          assertNotStyle(
-              $$(wallpaperSearchElement, '#error')!, 'display', 'none');
-          assertStyle(
-              $$(wallpaperSearchElement, '#wallpaperSearch')!, 'display',
-              'none');
+                assertNotStyle(
+                    $$(wallpaperSearchElement, '#error')!, 'display', 'none');
+                assertStyle(
+                    $$(wallpaperSearchElement, '#wallpaperSearch')!, 'display',
+                    'none');
+              });
         });
-
-    test('shows error ui if search fails', async () => {
-      handler.setResultFor(
-          'getWallpaperSearchResults',
-          Promise.resolve({status: WallpaperSearchStatus.kError, results: []}));
-      createWallpaperSearchElementWithDescriptors();
-      await flushTasks();
-
-      wallpaperSearchElement.$.submitButton.click();
-      await waitAfterNextRender(wallpaperSearchElement);
-
-      assertNotStyle($$(wallpaperSearchElement, '#error')!, 'display', 'none');
-      assertStyle(
-          $$(wallpaperSearchElement, '#wallpaperSearch')!, 'display', 'none');
-    });
   });
 });
diff --git a/chrome/test/data/webui/tab_search/tab_search_test_data.ts b/chrome/test/data/webui/tab_search/tab_search_test_data.ts
index b0538cd..3de6b34 100644
--- a/chrome/test/data/webui/tab_search/tab_search_test_data.ts
+++ b/chrome/test/data/webui/tab_search/tab_search_test_data.ts
@@ -217,9 +217,7 @@
 }
 
 export function sampleToken(high: bigint, low: bigint): Token {
-  const token = new Token();
-  token.high = high;
-  token.low = low;
+  const token: Token = {high, low};
   Object.freeze(token);
 
   return token;
diff --git a/chromecast/chromecast.gni b/chromecast/chromecast.gni
index 3047f9e..f04c5989 100644
--- a/chromecast/chromecast.gni
+++ b/chromecast/chromecast.gni
@@ -2,14 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/locales.gni")
 import("//components/cast_streaming/features.gni")
 import("//media/media_options.gni")
 
 # These args blocks should contain arguments used within the //chromecast
 # directory. Arguments which are used in other Chrome components should
-# be instead declared in //build/config/chromecast_build.gni.
+# be instead declared in //build/config/cast.gni.
 declare_args() {
   # True if Chromecast build is targeted for linux desktop. This type of build
   # is useful for testing and development, but currently supports only a subset
diff --git a/chromecast/media/audio/cast_audio_output_device.cc b/chromecast/media/audio/cast_audio_output_device.cc
index 9306a13..1ac7f43 100644
--- a/chromecast/media/audio/cast_audio_output_device.cc
+++ b/chromecast/media/audio/cast_audio_output_device.cc
@@ -256,7 +256,8 @@
       size_t io_buffer_size =
           audio_output_service::OutputSocket::kAudioMessageHeaderSize +
           filled_bytes;
-      auto io_buffer = base::MakeRefCounted<net::IOBuffer>(io_buffer_size);
+      auto io_buffer =
+          base::MakeRefCounted<net::IOBufferWithSize>(io_buffer_size);
       audio_bus_->ToInterleaved<::media::SignedInt16SampleTypeTraits>(
           frames_filled,
           reinterpret_cast<int16_t*>(
diff --git a/chromecast/media/audio/cast_audio_renderer.cc b/chromecast/media/audio/cast_audio_renderer.cc
index 208af7e..5bf3b4a 100644
--- a/chromecast/media/audio/cast_audio_renderer.cc
+++ b/chromecast/media/audio/cast_audio_renderer.cc
@@ -470,7 +470,7 @@
   size_t io_buffer_size =
       audio_output_service::OutputSocket::kAudioMessageHeaderSize +
       filled_bytes;
-  auto io_buffer = base::MakeRefCounted<net::IOBuffer>(io_buffer_size);
+  auto io_buffer = base::MakeRefCounted<net::IOBufferWithSize>(io_buffer_size);
   if (buffer->end_of_stream()) {
     OnEndOfStream();
     return;
diff --git a/chromecast/media/audio/net/audio_socket.cc b/chromecast/media/audio/net/audio_socket.cc
index 92ac593..9b5021d 100644
--- a/chromecast/media/audio/net/audio_socket.cc
+++ b/chromecast/media/audio/net/audio_socket.cc
@@ -175,8 +175,8 @@
       buffer = buffer_pool_->GetBuffer();
     }
     if (!buffer) {
-      buffer =
-          base::MakeRefCounted<net::IOBuffer>(sizeof(uint16_t) + total_size);
+      buffer = base::MakeRefCounted<net::IOBufferWithSize>(sizeof(uint16_t) +
+                                                           total_size);
     }
     ptr = buffer->data();
     base::WriteBigEndian(ptr, static_cast<uint16_t>(total_size));
diff --git a/chromecast/media/cma/backend/BUILD.gn b/chromecast/media/cma/backend/BUILD.gn
index 0537f9d..ac9d146 100644
--- a/chromecast/media/cma/backend/BUILD.gn
+++ b/chromecast/media/cma/backend/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//chromecast/chromecast.gni")
 import("//media/media_options.gni")
 
diff --git a/chromecast/media/cma/backend/alsa/BUILD.gn b/chromecast/media/cma/backend/alsa/BUILD.gn
index b82de5b3..7d6b4f47 100644
--- a/chromecast/media/cma/backend/alsa/BUILD.gn
+++ b/chromecast/media/cma/backend/alsa/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//chromecast/chromecast.gni")
 import("//media/media_options.gni")
 import("//testing/test.gni")
diff --git a/chromecast/media/cma/backend/mixer/BUILD.gn b/chromecast/media/cma/backend/mixer/BUILD.gn
index 91a772ea..d42add1 100644
--- a/chromecast/media/cma/backend/mixer/BUILD.gn
+++ b/chromecast/media/cma/backend/mixer/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//chromecast/chromecast.gni")
 import("//media/media_options.gni")
 
diff --git a/chromecast/media/cma/backend/video/BUILD.gn b/chromecast/media/cma/backend/video/BUILD.gn
index ce5fe3cf..487daef 100644
--- a/chromecast/media/cma/backend/video/BUILD.gn
+++ b/chromecast/media/cma/backend/video/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//chromecast/chromecast.gni")
 import("//media/media_options.gni")
 
diff --git a/chromecast/media/cma/pipeline/BUILD.gn b/chromecast/media/cma/pipeline/BUILD.gn
index 1b06326e..3cd6587b 100644
--- a/chromecast/media/cma/pipeline/BUILD.gn
+++ b/chromecast/media/cma/pipeline/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//chromecast/chromecast.gni")
 
 declare_args() {
diff --git a/chromecast/media/common/BUILD.gn b/chromecast/media/common/BUILD.gn
index ac8772b..466ce4d 100644
--- a/chromecast/media/common/BUILD.gn
+++ b/chromecast/media/common/BUILD.gn
@@ -5,7 +5,7 @@
 # Common modules that do not have any //media dependencies.
 
 import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//chromecast/chromecast.gni")
 
 group("all") {
diff --git a/chromecast/net/fake_stream_socket_unittest.cc b/chromecast/net/fake_stream_socket_unittest.cc
index 0701c1e..03a26e6 100644
--- a/chromecast/net/fake_stream_socket_unittest.cc
+++ b/chromecast/net/fake_stream_socket_unittest.cc
@@ -74,7 +74,7 @@
 }
 
 TEST_F(FakeStreamSocketTest, ReadAndWriteWithoutPeer) {
-  auto io_buffer = base::MakeRefCounted<net::IOBuffer>(1);
+  auto io_buffer = base::MakeRefCounted<net::IOBufferWithSize>(1);
   EXPECT_EQ(net::ERR_IO_PENDING,
             socket_1_.Read(io_buffer.get(), 1, base::BindOnce(&Callback)));
   EXPECT_EQ(net::ERR_SOCKET_NOT_CONNECTED,
@@ -91,7 +91,8 @@
       static_cast<int>(kData.size()),
       socket_1_.Write(send_buffer.get(), kData.size(),
                       base::BindOnce(&Callback), TRAFFIC_ANNOTATION_FOR_TESTS));
-  auto receive_buffer = base::MakeRefCounted<net::IOBuffer>(kData.size());
+  auto receive_buffer =
+      base::MakeRefCounted<net::IOBufferWithSize>(kData.size());
   ASSERT_EQ(static_cast<int>(kData.size()),
             socket_2_.Read(receive_buffer.get(), kData.size(),
                            base::BindOnce(&Callback)));
@@ -102,7 +103,8 @@
   socket_1_.SetPeer(&socket_2_);
   socket_2_.SetPeer(&socket_1_);
   const std::string kData("DATA");
-  auto receive_buffer = base::MakeRefCounted<net::IOBuffer>(kData.size());
+  auto receive_buffer =
+      base::MakeRefCounted<net::IOBufferWithSize>(kData.size());
   ASSERT_EQ(net::ERR_IO_PENDING,
             socket_2_.Read(receive_buffer.get(), kData.size(),
                            base::BindOnce(&Callback)));
@@ -127,7 +129,7 @@
                               base::BindOnce(&Callback),
                               TRAFFIC_ANNOTATION_FOR_TESTS));
   }
-  auto receive_buffer = base::MakeRefCounted<net::IOBuffer>(1024);
+  auto receive_buffer = base::MakeRefCounted<net::IOBufferWithSize>(1024);
   for (int i = 0; i < 1024; i++) {
     ASSERT_EQ(1024, socket_2_.Read(receive_buffer.get(), 1024,
                                    base::BindOnce(&Callback)));
diff --git a/chromecast/net/small_message_socket.cc b/chromecast/net/small_message_socket.cc
index fe9edcb..ea928a0d 100644
--- a/chromecast/net/small_message_socket.cc
+++ b/chromecast/net/small_message_socket.cc
@@ -122,7 +122,8 @@
     CHECK(new_buffer);
     new_buffer_size = buffer_pool_->buffer_size();
   } else {
-    new_buffer = base::MakeRefCounted<::net::IOBuffer>(current_size * 2);
+    new_buffer =
+        base::MakeRefCounted<::net::IOBufferWithSize>(current_size * 2);
     new_buffer_size = current_size * 2;
   }
   memcpy(new_buffer->data(), current_data, current_size);
@@ -419,7 +420,8 @@
 
     if (read_buffer_->size() < total_size) {
       // Current buffer is not big enough.
-      auto new_buffer = base::MakeRefCounted<::net::IOBuffer>(total_size);
+      auto new_buffer =
+          base::MakeRefCounted<::net::IOBufferWithSize>(total_size);
       memcpy(new_buffer->data(), read_buffer_->StartOfBuffer(), bytes_read);
       read_buffer_->SetUnderlyingBuffer(std::move(new_buffer), total_size);
       read_buffer_->DidConsume(bytes_read);
@@ -438,7 +440,7 @@
     if (extra_size > 0) {
       // Copy extra data to new buffer.
       if (extra_size > buffer_pool_->buffer_size()) {
-        new_buffer = base::MakeRefCounted<::net::IOBuffer>(extra_size);
+        new_buffer = base::MakeRefCounted<::net::IOBufferWithSize>(extra_size);
         new_buffer_size = extra_size;
       }
       memcpy(new_buffer->data(), old_buffer->data() + total_size, extra_size);
diff --git a/chromecast/net/small_message_socket_unittest.cc b/chromecast/net/small_message_socket_unittest.cc
index ed88923b..9865329 100644
--- a/chromecast/net/small_message_socket_unittest.cc
+++ b/chromecast/net/small_message_socket_unittest.cc
@@ -69,7 +69,8 @@
 
   void SendData(size_t size) {
     size_t data_offset = SmallMessageSocket::SizeDataBytes(size);
-    auto buffer = base::MakeRefCounted<net::IOBuffer>(data_offset + size);
+    auto buffer =
+        base::MakeRefCounted<net::IOBufferWithSize>(data_offset + size);
     SmallMessageSocket::WriteSizeData(buffer->data(), size);
     SetData(buffer->data() + data_offset, size);
     SendBuffer(std::move(buffer), size + data_offset);
diff --git a/chromeos/ash/components/osauth/public/auth_session_storage.h b/chromeos/ash/components/osauth/public/auth_session_storage.h
index f41eeff..20b3535ab 100644
--- a/chromeos/ash/components/osauth/public/auth_session_storage.h
+++ b/chromeos/ash/components/osauth/public/auth_session_storage.h
@@ -21,7 +21,7 @@
 
 class UserContext;
 
-class ScopedSessionRefresher {
+class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_OSAUTH) ScopedSessionRefresher {
  public:
   ScopedSessionRefresher(const ScopedSessionRefresher&) = delete;
   ScopedSessionRefresher& operator=(const ScopedSessionRefresher&) = delete;
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 1ea8de5..61550d0f 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -2521,7 +2521,7 @@
           Downloading the screen saver
         </message>
         <message name="IDS_PERSONALIZATION_APP_AMBIENT_MODE_PAGE_DESCRIPTION" desc="Description for the ambient mode settings page.">
-          When your screen is idle, show photos, time, weather, and media info.
+          When your screen is idle, show photos, time, weather, and media info
         </message>
         <message name="IDS_PERSONALIZATION_APP_AMBIENT_MODE_ON" desc="Label for the toggle row in ambient mode settings page when it is enabled.">
           On
diff --git a/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_AMBIENT_MODE_PAGE_DESCRIPTION.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_AMBIENT_MODE_PAGE_DESCRIPTION.png.sha1
index 8ee1b8b0..5d12977 100644
--- a/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_AMBIENT_MODE_PAGE_DESCRIPTION.png.sha1
+++ b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_AMBIENT_MODE_PAGE_DESCRIPTION.png.sha1
@@ -1 +1 @@
-1e5da7022fe5244bf02d9c49367d7f4dc86b153a
\ No newline at end of file
+4fd16e85c9f14f6f86b04ac88c6982b0e52199e6
\ No newline at end of file
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom
index 4fd0654..57e058f 100644
--- a/chromeos/crosapi/mojom/crosapi.mojom
+++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -1658,8 +1658,8 @@
 // has accidentally become a kitchen sink for different features. This was not
 // intentional.
 //
-// Next MinVersion: 74.
-// Next ID: 21
+// Next MinVersion: 75.
+// Next ID: 22
 //
 [Stable, Uuid="4e04dc16-b34c-40fd-9e3f-3c55c2c6cf91",
  RenamedFrom="crosapi.mojom.LacrosChromeService"]
@@ -1816,6 +1816,10 @@
   [MinVersion=70]
   Launch@19([MinVersion=72] int64 target_display_id)
       => ([MinVersion=73] CreationResult result);
+
+  // Opens the Lacros profile manger window.
+  [MinVersion=74]
+  OpenProfileManager@21();
 };
 
 // TODO(crbug.com/1180712): move to its own file. Currently due to circular
diff --git a/chromeos/ui/frame/BUILD.gn b/chromeos/ui/frame/BUILD.gn
index 89db48c..7621478 100644
--- a/chromeos/ui/frame/BUILD.gn
+++ b/chromeos/ui/frame/BUILD.gn
@@ -77,12 +77,14 @@
     "//chromeos/ui/base",
     "//chromeos/ui/vector_icons",
     "//chromeos/ui/wm",
+    "//chromeos/utils",
     "//components/prefs",
     "//skia",
     "//ui/aura",
     "//ui/base",
     "//ui/chromeos/styles:cros_tokens_color_mappings_generator",
     "//ui/color",
+    "//ui/events/devices:devices",
     "//ui/platform_window",
     "//ui/strings:ui_strings_grit",
     "//ui/views",
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.cc b/chromeos/ui/frame/caption_buttons/frame_size_button.cc
index 6ad3d42..f9a3926 100644
--- a/chromeos/ui/frame/caption_buttons/frame_size_button.cc
+++ b/chromeos/ui/frame/caption_buttons/frame_size_button.cc
@@ -15,6 +15,7 @@
 #include "chromeos/ui/frame/frame_utils.h"
 #include "chromeos/ui/frame/multitask_menu/multitask_menu.h"
 #include "chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.h"
+#include "chromeos/utils/haptics_util.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
@@ -22,6 +23,7 @@
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/display/tablet_state.h"
+#include "ui/events/devices/haptic_touchpad_effects.h"
 #include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/canvas.h"
@@ -260,6 +262,10 @@
   multitask_menu_widget_->Show();
   delegate_->GetMultitaskMenuNudgeController()->OnMenuOpened(
       /*tablet_mode=*/false);
+
+  haptics_util::PlayHapticTouchpadEffect(
+      ui::HapticTouchpadEffect::kSnap,
+      ui::HapticTouchpadEffectStrength::kMedium);
 }
 
 void FrameSizeButton::ToggleMultitaskMenu() {
diff --git a/chromeos/ui/frame/multitask_menu/multitask_button.cc b/chromeos/ui/frame/multitask_menu/multitask_button.cc
index 6c6060a..349a57f 100644
--- a/chromeos/ui/frame/multitask_menu/multitask_button.cc
+++ b/chromeos/ui/frame/multitask_menu/multitask_button.cc
@@ -5,7 +5,9 @@
 #include "chromeos/ui/frame/multitask_menu/multitask_button.h"
 
 #include "chromeos/ui/frame/multitask_menu/multitask_menu_constants.h"
+#include "chromeos/utils/haptics_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/events/devices/haptic_touchpad_effects.h"
 #include "ui/gfx/canvas.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/controls/highlight_path_generator.h"
@@ -28,6 +30,14 @@
   SetAccessibleName(name);
 }
 
+void MultitaskButton::StateChanged(views::Button::ButtonState old_state) {
+  if (GetState() == views::Button::STATE_HOVERED) {
+    haptics_util::PlayHapticTouchpadEffect(
+        ui::HapticTouchpadEffect::kSnap,
+        ui::HapticTouchpadEffectStrength::kMedium);
+  }
+}
+
 void MultitaskButton::PaintButtonContents(gfx::Canvas* canvas) {
   cc::PaintFlags fill_flags;
   fill_flags.setAntiAlias(true);
diff --git a/chromeos/ui/frame/multitask_menu/multitask_button.h b/chromeos/ui/frame/multitask_menu/multitask_button.h
index a4713b7..40876dd8 100644
--- a/chromeos/ui/frame/multitask_menu/multitask_button.h
+++ b/chromeos/ui/frame/multitask_menu/multitask_button.h
@@ -32,6 +32,7 @@
   ~MultitaskButton() override = default;
 
   // views::Button:
+  void StateChanged(views::Button::ButtonState old_state) override;
   void PaintButtonContents(gfx::Canvas* canvas) override;
 
  private:
diff --git a/chromeos/ui/frame/multitask_menu/split_button_view.cc b/chromeos/ui/frame/multitask_menu/split_button_view.cc
index 9b689d4e..5de1f0bd 100644
--- a/chromeos/ui/frame/multitask_menu/split_button_view.cc
+++ b/chromeos/ui/frame/multitask_menu/split_button_view.cc
@@ -8,8 +8,10 @@
 
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "chromeos/ui/frame/frame_utils.h"
+#include "chromeos/utils/haptics_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/events/devices/haptic_touchpad_effects.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/geometry/point_f.h"
@@ -100,6 +102,19 @@
   void set_button_color(SkColor color) { button_color_ = color; }
 
   // views::Button:
+  void StateChanged(views::Button::ButtonState old_state) override {
+    if (GetState() == views::Button::STATE_HOVERED) {
+      haptics_util::PlayHapticTouchpadEffect(
+          ui::HapticTouchpadEffect::kSnap,
+          ui::HapticTouchpadEffectStrength::kMedium);
+    }
+
+    if (IsHoveredOrPressedState(old_state) ||
+        IsHoveredOrPressedState(GetState())) {
+      hovered_pressed_callback_.Run();
+    }
+  }
+
   void OnPaintBackground(gfx::Canvas* canvas) override {
     cc::PaintFlags pattern_flags;
     pattern_flags.setAntiAlias(true);
@@ -114,13 +129,6 @@
     canvas->DrawRoundRect(pattern_bounds, kButtonCornerRadius, pattern_flags);
   }
 
-  void StateChanged(ButtonState old_state) override {
-    if (IsHoveredOrPressedState(old_state) ||
-        IsHoveredOrPressedState(GetState())) {
-      hovered_pressed_callback_.Run();
-    }
-  }
-
  private:
   SkColor button_color_ = SK_ColorTRANSPARENT;
   // The inset between the button window pattern and the border.
diff --git a/clank b/clank
index f75c7cbd..c000cb7 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit f75c7cbd6dde5dd650d3052569eef08b0375ec10
+Subproject commit c000cb71605baf6bfb5e5bcc6765491ccedc7369
diff --git a/components/browser_ui/settings/android/java/res/values/styles.xml b/components/browser_ui/settings/android/java/res/values/styles.xml
index 9516ea04..2f06301d 100644
--- a/components/browser_ui/settings/android/java/res/values/styles.xml
+++ b/components/browser_ui/settings/android/java/res/values/styles.xml
@@ -68,6 +68,7 @@
     </style>
 
     <style name="SwitchPreference" parent="Preference.SwitchPreferenceCompat.Material">
+        <item name="android:widgetLayout">@layout/preference_switch</item>
         <item name="allowDividerAbove">true</item>
         <item name="allowDividerBelow">true</item>
         <item name="iconSpaceReserved">false</item>
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java
index ed9f497c1..7b2b900 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java
@@ -8,7 +8,6 @@
 
 import androidx.annotation.Nullable;
 
-import org.chromium.base.MathUtils;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridge.StorageInfoClearedCallback;
 import org.chromium.components.content_settings.ContentSettingValues;
@@ -146,7 +145,7 @@
      */
     public int compareByStorageTo(Website to) {
         if (this == to) return 0;
-        return MathUtils.compareLongs(to.getTotalUsage(), getTotalUsage());
+        return Long.compare(to.getTotalUsage(), getTotalUsage());
     }
 
     /**
diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd
index e2f01dc..c272286 100644
--- a/components/browser_ui/strings/android/browser_ui_strings.grd
+++ b/components/browser_ui/strings/android/browser_ui_strings.grd
@@ -639,6 +639,9 @@
       <message name="IDS_PAGE_INFO_TRACKING_PROTECTION_DESCRIPTION" desc="Description text for the Tracking Protection subpage in the page info view. Contains a link to the Tracking Protection settings page.">
         Chrome limits most sites from using third-party cookies to track you as you browse. Visit settings to <ph name="BEGIN_LINK">&lt;link&gt;</ph>manage your tracking protections<ph name="END_LINK">&lt;/link&gt;</ph>
       </message>
+      <message name="IDS_PAGE_INFO_TRACKING_PROTECTION_SITE_GRANT_DESCRIPTION" desc="Description text for the Tracking Protection subpage in the page info view for when a site has a TPCD grant. Contains a link to the Tracking Protection settings page.">
+        Chrome limits most sites from using third-party cookies. But third-party cookies are allowed on this site because it relies on them to provide basic services.\n\nVisit settings to <ph name="BEGIN_LINK">&lt;link&gt;</ph>manage your tracking protections<ph name="END_LINK">&lt;/link&gt;</ph>.
+      </message>
       <message name="IDS_PAGE_INFO_TRACKING_PROTECTION_BLOCKED_COOKIES_DESCRIPTION" desc="Description text for the Tracking Protection subpage in the page info view if all cookies are blocked. Contains a link to the Tracking Protection settings page.">
         You blocked sites from using third-party cookies to track you as you browse. Visit settings to <ph name="BEGIN_LINK">&lt;link&gt;</ph>manage your tracking protections<ph name="END_LINK">&lt;/link&gt;</ph>.
       </message>
diff --git a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_INFO_TRACKING_PROTECTION_SITE_GRANT_DESCRIPTION.png.sha1 b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_INFO_TRACKING_PROTECTION_SITE_GRANT_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..fc5df4f
--- /dev/null
+++ b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_INFO_TRACKING_PROTECTION_SITE_GRANT_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+6d3385af5f6558abca8d81d716ec027670182286
\ No newline at end of file
diff --git a/components/browser_ui/styles/android/BUILD.gn b/components/browser_ui/styles/android/BUILD.gn
index 986d99ca..c1a1d4da 100644
--- a/components/browser_ui/styles/android/BUILD.gn
+++ b/components/browser_ui/styles/android/BUILD.gn
@@ -24,8 +24,6 @@
   sources = [
     "java/res/color-night/new_tab_button_pressed_tint_list.xml",
     "java/res/color-night/new_tab_button_tint_list.xml",
-    "java/res/color-night/switch_thumb_tint_list.xml",
-    "java/res/color-night/switch_track_tint.xml",
     "java/res/color/chip_text_color_secondary_list.xml",
     "java/res/color/color_primary_with_alpha_10.xml",
     "java/res/color/color_primary_with_alpha_15.xml",
@@ -53,10 +51,6 @@
     "java/res/color/new_tab_button_tint_list.xml",
     "java/res/color/progress_bar_bg_color_list.xml",
     "java/res/color/selection_control_button_tint_list.xml",
-    "java/res/color/switch_thumb_tint_incognito_baseline_list.xml",
-    "java/res/color/switch_thumb_tint_list.xml",
-    "java/res/color/switch_track_tint.xml",
-    "java/res/color/switch_track_tint_incognito_baseline_list.xml",
     "java/res/color/target_view_color_list.xml",
     "java/res/color/text_button_ripple_color_list.xml",
     "java/res/color/text_highlight_color.xml",
diff --git a/components/browser_ui/styles/android/java/res/color-night/switch_thumb_tint_list.xml b/components/browser_ui/styles/android/java/res/color-night/switch_thumb_tint_list.xml
deleted file mode 100644
index 669177a..0000000
--- a/components/browser_ui/styles/android/java/res/color-night/switch_thumb_tint_list.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@macro/switch_thumb_disabled_color" android:state_enabled="false"/>
-    <item android:color="@macro/default_control_color_active" android:state_checked="true"/>
-    <item android:color="@macro/switch_enabled_unchecked_color_light"/>
-</selector>
diff --git a/components/browser_ui/styles/android/java/res/color-night/switch_track_tint.xml b/components/browser_ui/styles/android/java/res/color-night/switch_track_tint.xml
deleted file mode 100644
index 565a8e7..0000000
--- a/components/browser_ui/styles/android/java/res/color-night/switch_track_tint.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="@dimen/switch_track_disabled_alpha"
-        android:color="@macro/switch_track_disabled_color" android:state_enabled="false"/>
-    <item android:alpha="@dimen/switch_track_enabled_alpha"
-        android:color="@macro/default_control_color_active" android:state_checked="true"/>
-    <item android:alpha="@dimen/switch_track_enabled_alpha"
-        android:color="@macro/switch_enabled_unchecked_color_light"/>
-</selector>
diff --git a/components/browser_ui/styles/android/java/res/color/switch_thumb_tint_incognito_baseline_list.xml b/components/browser_ui/styles/android/java/res/color/switch_thumb_tint_incognito_baseline_list.xml
deleted file mode 100644
index 08e01db..0000000
--- a/components/browser_ui/styles/android/java/res/color/switch_thumb_tint_incognito_baseline_list.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@color/switch_thumb_disabled_color_baseline_dark" android:state_enabled="false"/>
-    <item android:color="@color/default_control_color_active_dark" android:state_checked="true"/>
-    <item android:color="@color/switch_enabled_unchecked_color_baseline_light"/>
-</selector>
diff --git a/components/browser_ui/styles/android/java/res/color/switch_thumb_tint_list.xml b/components/browser_ui/styles/android/java/res/color/switch_thumb_tint_list.xml
deleted file mode 100644
index 5c01cd1..0000000
--- a/components/browser_ui/styles/android/java/res/color/switch_thumb_tint_list.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@macro/switch_thumb_disabled_color" android:state_enabled="false"/>
-    <item android:color="@macro/default_control_color_active" android:state_checked="true"/>
-    <item android:color="@macro/switch_enabled_unchecked_color_dark"/>
-</selector>
diff --git a/components/browser_ui/styles/android/java/res/color/switch_track_tint.xml b/components/browser_ui/styles/android/java/res/color/switch_track_tint.xml
deleted file mode 100644
index 48a4a1f..0000000
--- a/components/browser_ui/styles/android/java/res/color/switch_track_tint.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="@dimen/switch_track_disabled_alpha"
-        android:color="@macro/switch_track_disabled_color" android:state_enabled="false"/>
-    <item android:alpha="@dimen/switch_track_enabled_alpha"
-        android:color="@macro/default_control_color_active" android:state_checked="true"/>
-    <item android:alpha="@dimen/switch_track_enabled_alpha"
-        android:color="@macro/switch_enabled_unchecked_color_dark"/>
-</selector>
diff --git a/components/browser_ui/styles/android/java/res/color/switch_track_tint_incognito_baseline_list.xml b/components/browser_ui/styles/android/java/res/color/switch_track_tint_incognito_baseline_list.xml
deleted file mode 100644
index 2e0cb86..0000000
--- a/components/browser_ui/styles/android/java/res/color/switch_track_tint_incognito_baseline_list.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="@dimen/switch_track_disabled_alpha"
-        android:color="@color/switch_track_disabled_color_baseline_light" android:state_enabled="false"/>
-    <item android:alpha="@dimen/switch_track_enabled_alpha"
-        android:color="@color/default_control_color_active_dark" android:state_checked="true"/>
-    <item android:alpha="@dimen/switch_track_enabled_alpha"
-        android:color="@color/switch_enabled_unchecked_color_baseline_light"/>
-</selector>
diff --git a/components/browser_ui/styles/android/java/res/values-night/colors.xml b/components/browser_ui/styles/android/java/res/values-night/colors.xml
index bdcdb30..b859e6e 100644
--- a/components/browser_ui/styles/android/java/res/values-night/colors.xml
+++ b/components/browser_ui/styles/android/java/res/values-night/colors.xml
@@ -12,8 +12,6 @@
     <!-- Control colors for toggles, checkboxes, radio buttons, list item highlight, and accent.
          Note that these should NOT be used for icon tint. -->
     <color name="control_highlight_color">@color/default_control_color_highlight_dark</color>
-    <color name="switch_track_disabled_color_baseline">@color/switch_track_disabled_color_baseline_light</color>
-    <color name="switch_thumb_disabled_color_baseline">@color/switch_thumb_disabled_color_baseline_dark</color>
 
     <!-- Empty states colors -->
     <color name="empty_state_icon_color">@color/material_primary_80</color>
diff --git a/components/browser_ui/styles/android/java/res/values/colors.xml b/components/browser_ui/styles/android/java/res/values/colors.xml
index d1c1a6a..ddb8dc34 100644
--- a/components/browser_ui/styles/android/java/res/values/colors.xml
+++ b/components/browser_ui/styles/android/java/res/values/colors.xml
@@ -26,12 +26,6 @@
     <color name="control_highlight_color" tools:ignore="UnusedResources">
         @color/default_control_color_highlight_light
     </color>
-    <color name="switch_enabled_unchecked_color_baseline_dark" tools:ignore="UnusedResources">@color/baseline_neutral_variant_50</color>
-    <color name="switch_enabled_unchecked_color_baseline_light">@color/baseline_neutral_90</color>
-    <color name="switch_track_disabled_color_baseline" tools:ignore="UnusedResources">@color/baseline_neutral_10</color>
-    <color name="switch_track_disabled_color_baseline_light">@color/baseline_neutral_90</color>
-    <color name="switch_thumb_disabled_color_baseline" tools:ignore="UnusedResources">@color/baseline_neutral_95</color>
-    <color name="switch_thumb_disabled_color_baseline_dark">@color/baseline_neutral_20</color>
 
     <!-- Favicons -->
     <color name="default_favicon_background_color">@color/default_control_color_normal_light</color>
diff --git a/components/browser_ui/styles/android/java/res/values/dimens.xml b/components/browser_ui/styles/android/java/res/values/dimens.xml
index 78ee276..ff2dbb4 100644
--- a/components/browser_ui/styles/android/java/res/values/dimens.xml
+++ b/components/browser_ui/styles/android/java/res/values/dimens.xml
@@ -24,8 +24,6 @@
     <item name="icon_animated_faded_alpha" format="float" type="dimen">0.3</item>
     <item name="text_highlight_alpha" format="float" type="dimen">0.2</item>
     <item name="progress_bar_bg_alpha" format="float" type="dimen">0.2</item>
-    <item name="switch_track_disabled_alpha" format="float" type="dimen">0.12</item>
-    <item name="switch_track_enabled_alpha" format="float" type="dimen">0.3</item>
     <item name="filled_button_bg_disabled_alpha" format="float" type="dimen">0.12</item>
 
     <!-- Target view values for various things -->
diff --git a/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml b/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml
index 5d2a8e5..0751e425 100644
--- a/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml
+++ b/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml
@@ -24,11 +24,6 @@
     <macro name="default_text_color_on_accent2_container">?attr/colorOnSecondaryContainer</macro>
     <macro name="default_text_color_secondary" tools:ignore="UnusedResources">?attr/colorOnSurfaceVariant</macro>
 
-    <macro name="switch_enabled_unchecked_color_dark">?attr/colorOutline</macro>
-    <macro name="switch_enabled_unchecked_color_light">?attr/colorOnSurface</macro>
-    <macro name="switch_track_disabled_color">?attr/colorOnSurface</macro>
-    <macro name="switch_thumb_disabled_color">?attr/colorOnSurfaceInverse</macro>
-
     <macro name="hairline_stroke_color">?attr/colorOutline</macro>
     <macro name="divider_line_bg_color">?attr/colorSurfaceVariant</macro>
     <macro name="drag_handlebar_color" tools:ignore="UnusedResources">@macro/divider_line_bg_color</macro>
diff --git a/components/browser_ui/styles/android/java/res/values/styles.xml b/components/browser_ui/styles/android/java/res/values/styles.xml
index 1f373fc..1ec8693 100644
--- a/components/browser_ui/styles/android/java/res/values/styles.xml
+++ b/components/browser_ui/styles/android/java/res/values/styles.xml
@@ -19,15 +19,13 @@
         <item name="android:minHeight">0dp</item>
         <item name="android:textAppearance">@style/TextAppearance.TextMedium.Primary</item>
     </style>
-    <style name="Widget.BrowserUI.Switch" parent="Widget.MaterialComponents.CompoundButton.Switch">
-        <item name="thumbTint">@color/switch_thumb_tint_list</item>
-        <item name="trackTint">@color/switch_track_tint</item>
-        <item name="trackTintMode">src_in</item>
+    <style name="Widget.BrowserUI.Switch" parent="Widget.Material3.CompoundButton.MaterialSwitch">
+        <item name="android:scaleX">@fraction/material_switch_scale_fraction</item>
+        <item name="android:scaleY">@fraction/material_switch_scale_fraction</item>
+        <item name="android:minHeight">@dimen/switch_pre_scale_min_height</item>
     </style>
-    <style name="Widget.BrowserUI.Switch.Incognito" parent="Widget.MaterialComponents.CompoundButton.Switch">
-        <item name="thumbTint">@color/switch_thumb_tint_incognito_baseline_list</item>
-        <item name="trackTint">@color/switch_track_tint_incognito_baseline_list</item>
-
+    <style name="Widget.BrowserUI.Switch.Incognito">
+        <item name="materialThemeOverlay">@style/ThemeOverlay.BrowserUI.Switch.Incognito</item>
     </style>
     <!-- TextInputLayout style -->
     <style name="Widget.BrowserUI.TextInputLayout" parent="Widget.Design.TextInputLayout">
@@ -79,18 +77,6 @@
         <item name="android:indeterminateTint">@macro/default_icon_color_accent1</item>
     </style>
 
-    <!-- Switch styling for dark theme -->
-    <!-- TODO(sinansahin): See if we can pass the baseline dark theme to the incognito NTP instead.
-         -->
-    <style name="SwitchMaterialDark">
-        <!-- TODO(sinansahin): When we migrate the switch style to Material3, we should override
-             colorOnSurface and colorPrimary instead of these attributes because they are what
-             m3_selection_control_ripple_color_selector uses. -->
-        <item name="colorControlActivated">@color/default_control_color_active_dark</item>
-        <item name="colorControlHighlight">@color/default_control_color_highlight_dark</item>
-        <item name="switchStyle">@style/Widget.BrowserUI.Switch.Incognito</item>
-    </style>
-
     <!-- Styling for an app menu item row. -->
     <style name="AppMenuItem">
         <item name="android:paddingStart">16dp</item>
diff --git a/components/browser_ui/styles/android/java/res/values/themes.xml b/components/browser_ui/styles/android/java/res/values/themes.xml
index 3056af8..f0f02fc 100644
--- a/components/browser_ui/styles/android/java/res/values/themes.xml
+++ b/components/browser_ui/styles/android/java/res/values/themes.xml
@@ -62,4 +62,17 @@
         <!-- Click event uses dark mode colors -->
         <item name="colorControlHighlight">@color/ripple_material_dark</item>
     </style>
+    <!-- Incognito switch theme overlay -->
+    <!-- TODO(sinansahin): See if we can pass the baseline dark theme to the incognito NTP instead.
+         -->
+    <style name="ThemeOverlay.BrowserUI.Switch.Incognito" parent="">
+        <item name="colorSurface">@color/baseline_neutral_10</item>
+        <item name="colorOnSurface">@color/baseline_neutral_90</item>
+        <item name="colorOnSurfaceVariant">@color/baseline_neutral_variant_80</item>
+        <item name="colorSurfaceVariant">@color/baseline_neutral_variant_30</item>
+        <item name="colorPrimary">@color/baseline_primary_80</item>
+        <item name="colorOnPrimary">@color/baseline_primary_20</item>
+        <item name="colorPrimaryContainer">@color/baseline_primary_30</item>
+        <item name="colorOutline">@color/baseline_neutral_variant_60</item>
+    </style>
 </resources>
diff --git a/components/browser_ui/theme/android/java/res/values/themes.xml b/components/browser_ui/theme/android/java/res/values/themes.xml
index 1ef3b60..d1e58f19 100644
--- a/components/browser_ui/theme/android/java/res/values/themes.xml
+++ b/components/browser_ui/theme/android/java/res/values/themes.xml
@@ -60,6 +60,12 @@
         <item name="globalOutlinedButtonBorderColor">@macro/divider_line_bg_color</item>
         <item name="globalLinkTextColor">?attr/colorPrimary</item>
         <item name="globalClickableSpanColor">?attr/colorPrimary</item>
+
+        <item name="materialSwitchStyle">@style/Widget.BrowserUI.Switch</item>
+
+        <!-- Switches style workaround for UI that might use SwitchPreferenceCompat while not
+         using the theme for SettingsActivity (e.g. PageInfoView) -->
+        <item name="switchPreferenceCompatStyle">@style/SwitchPreference</item>
     </style>
     <style name="Base.V31.Theme.BrowserUI" parent="Base.V21.Theme.BrowserUI" />
     <style name="Base.Theme.BrowserUI" parent="Base.V31.Theme.BrowserUI" />
@@ -67,7 +73,7 @@
         <!-- Control styles -->
         <item name="checkboxStyle">@style/Widget.BrowserUI.CheckBox</item>
         <item name="radioButtonStyle">@style/Widget.BrowserUI.RadioButton</item>
-        <item name="switchStyle">@style/Widget.BrowserUI.Switch</item>
+        <item name="materialSwitchStyle">@style/Widget.BrowserUI.Switch</item>
 
         <!-- Window Properties -->
         <item name="android:windowBackground">@macro/default_bg_color</item>
@@ -153,6 +159,12 @@
         <item name="globalOutlinedButtonBorderColor">@macro/divider_line_bg_color</item>
         <item name="globalLinkTextColor">?attr/colorPrimary</item>
         <item name="globalClickableSpanColor">?attr/colorPrimary</item>
+
+        <!-- Widgets style override-->
+        <item name="materialSwitchStyle">@style/Widget.BrowserUI.Switch</item>
+        <!-- Switches style workaround for UI that might use SwitchPreferenceCompat while not
+         using the theme for SettingsActivity (e.g. PageInfoView) -->
+        <item name="switchPreferenceCompatStyle">@style/SwitchPreference</item>
     </style>
     <!-- Overridden by night mode. -->
     <style name="Theme.BrowserUI.DialogWhenLarge.DayNight" parent="Theme.BrowserUI.DialogWhenLarge"/>
@@ -219,6 +231,10 @@
 
         <!--  Overriding AppCompat values -->
         <item name="spinnerStyle">@style/SpinnerStyle</item>
+        <item name="materialSwitchStyle">@style/Widget.BrowserUI.Switch</item>
+        <!-- Switches style workaround for UI that might use SwitchPreferenceCompat while not
+         using the theme for SettingsActivity (e.g. PageInfoView) -->
+        <item name="switchPreferenceCompatStyle">@style/SwitchPreference</item>
 
         <!-- Depending on if the support library or framework is inflating the
              dialog, a different layout is used, that names this style slightly
diff --git a/components/browser_ui/widget/android/BUILD.gn b/components/browser_ui/widget/android/BUILD.gn
index e272488..1332880 100644
--- a/components/browser_ui/widget/android/BUILD.gn
+++ b/components/browser_ui/widget/android/BUILD.gn
@@ -26,6 +26,7 @@
     "java/src/org/chromium/components/browser_ui/widget/InsetObserverSupplier.java",
     "java/src/org/chromium/components/browser_ui/widget/MaterialCardViewNoShadow.java",
     "java/src/org/chromium/components/browser_ui/widget/MaterialProgressBar.java",
+    "java/src/org/chromium/components/browser_ui/widget/MaterialSwitchWithText.java",
     "java/src/org/chromium/components/browser_ui/widget/MenuOrKeyboardActionController.java",
     "java/src/org/chromium/components/browser_ui/widget/MoreProgressButton.java",
     "java/src/org/chromium/components/browser_ui/widget/NumberRollView.java",
@@ -236,9 +237,11 @@
     "java/res/layout/empty_state_view.xml",
     "java/res/layout/expand_arrow_with_separator.xml",
     "java/res/layout/indeterminate_progress_view.xml",
+    "java/res/layout/material_switch_with_text.xml",
     "java/res/layout/modern_list_item_view.xml",
     "java/res/layout/more_progress_button.xml",
     "java/res/layout/number_roll_view.xml",
+    "java/res/layout/preference_switch.xml",
     "java/res/layout/promo_card_view_compact.xml",
     "java/res/layout/promo_card_view_large.xml",
     "java/res/layout/promo_card_view_slim.xml",
diff --git a/components/browser_ui/widget/android/java/res/layout/material_switch_with_text.xml b/components/browser_ui/widget/android/java/res/layout/material_switch_with_text.xml
new file mode 100644
index 0000000..06815abd
--- /dev/null
+++ b/components/browser_ui/widget/android/java/res/layout/material_switch_with_text.xml
@@ -0,0 +1,21 @@
+<!--
+Copyright 2023 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <org.chromium.ui.widget.TextViewWithLeading
+        android:id="@+id/switch_text"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:focusable="false"
+        android:textAppearance="@style/TextAppearance.TextLarge.Primary"
+        android:layout_weight="1" />
+
+    <include layout="@layout/preference_switch"
+        android:id="@+id/switch_widget"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="end"
+        android:focusable="false" />
+</merge>
diff --git a/components/browser_ui/widget/android/java/res/layout/preference_switch.xml b/components/browser_ui/widget/android/java/res/layout/preference_switch.xml
new file mode 100644
index 0000000..3867152
--- /dev/null
+++ b/components/browser_ui/widget/android/java/res/layout/preference_switch.xml
@@ -0,0 +1,14 @@
+<!--
+Copyright 2023 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<com.google.android.material.materialswitch.MaterialSwitch
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/Widget.BrowserUI.Switch"
+    android:id="@+id/switchWidget"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:focusable="false"
+    android:clickable="false"
+    android:background="@null"/>
diff --git a/components/browser_ui/widget/android/java/res/values/dimens.xml b/components/browser_ui/widget/android/java/res/values/dimens.xml
index 7eee70a..ab07ee0 100644
--- a/components/browser_ui/widget/android/java/res/values/dimens.xml
+++ b/components/browser_ui/widget/android/java/res/values/dimens.xml
@@ -198,4 +198,11 @@
     <dimen name="empty_state_subheading_padding_top">8dp</dimen>
     <!-- Surface Polish -->
     <dimen name="home_surface_background_color_elevation">@dimen/default_elevation_2</dimen>
+
+    <!-- Preference switch -->
+    <!-- Work around to adopt the material switch . See crbug/1248590. -->
+    <item type="fraction" name="material_switch_scale_fraction">0.8</item>
+    <!-- Min height required to satisfy the min touch target size-->
+    <dimen name="switch_pre_scale_min_height">60dp</dimen>
+    <dimen name="switch_with_text_min_height">@dimen/min_touch_target_size</dimen>
 </resources>
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/MaterialSwitchWithText.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/MaterialSwitchWithText.java
new file mode 100644
index 0000000..147103e
--- /dev/null
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/MaterialSwitchWithText.java
@@ -0,0 +1,102 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.browser_ui.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Checkable;
+import android.widget.CompoundButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+
+import com.google.android.material.materialswitch.MaterialSwitch;
+
+/**
+ * Chrome workaround for material switch wrapped within a layout to scale down the size of the
+ * switch, while maintaining the size of the text.
+ *
+ * <p>Note that this class has many limitations, so features that'd like to further customize the
+ * behavior of the switch and text are highly recommended to implement their own TextView +
+ * MaterialSwitch in the layout.
+ *
+ * <p>The limitations including but not limited to:
+ *
+ * <ul>
+ *   Resource attribute defined in xml for {@link MaterialSwitch} are not forwarded to the wrapped
+ *   switch (e.g. android:textAppearance)
+ * </ul>
+ *
+ * <ul>
+ *   The ability to perform long-press & drag to flip the switch is disabled, due to having the
+ *   LinearLayout to be focusable to have a consistent behavior with MaterialSwitch in talkback.
+ *   This behavior makes it similar to the behavior as a SwitchPreferenceCompat.
+ * </ul>
+ */
+public class MaterialSwitchWithText extends LinearLayout implements Checkable, OnClickListener {
+    private final MaterialSwitch mSwitch;
+    private final TextView mTextView;
+
+    public MaterialSwitchWithText(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public MaterialSwitchWithText(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        LayoutInflater.from(context).inflate(R.layout.material_switch_with_text, this);
+
+        setOrientation(LinearLayout.HORIZONTAL);
+        setGravity(Gravity.CENTER_VERTICAL);
+        setMinimumHeight(getResources().getDimensionPixelSize(R.dimen.switch_with_text_min_height));
+        setFocusable(true);
+
+        mTextView = findViewById(R.id.switch_text);
+        mSwitch = findViewById(R.id.switch_widget);
+
+        setOnClickListener(this);
+
+        TypedArray textStyles =
+                getContext().obtainStyledAttributes(attrs, new int[] {android.R.attr.text});
+        @StringRes int textId = textStyles.getResourceId(0, 0);
+        if (textId != 0) mTextView.setText(textId);
+        textStyles.recycle();
+    }
+
+    @Override
+    public void setChecked(boolean checked) {
+        mSwitch.setChecked(checked);
+    }
+
+    @Override
+    public boolean isChecked() {
+        return mSwitch.isChecked();
+    }
+
+    @Override
+    public void toggle() {
+        mSwitch.toggle();
+    }
+
+    @Override
+    public void onClick(View view) {
+        toggle();
+    }
+
+    /**
+     * Set the OnCheckedChangeListener for the switch.
+     *
+     * @see CompoundButton#setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener).
+     */
+    public void setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener listener) {
+        mSwitch.setOnCheckedChangeListener(listener);
+    }
+}
diff --git a/components/browsing_data/content/browsing_data_helper.cc b/components/browsing_data/content/browsing_data_helper.cc
index 0abe4939..e962896 100644
--- a/components/browsing_data/content/browsing_data_helper.cc
+++ b/components/browsing_data/content/browsing_data_helper.cc
@@ -188,10 +188,6 @@
     HostContentSettingsMap::PatternSourcePredicate pattern_predicate,
     HostContentSettingsMap* host_content_settings_map) {
   host_content_settings_map->ClearSettingsForOneTypeWithPredicate(
-      ContentSettingsType::FEDERATED_IDENTITY_ACTIVE_SESSION, delete_begin,
-      delete_end, pattern_predicate);
-
-  host_content_settings_map->ClearSettingsForOneTypeWithPredicate(
       ContentSettingsType::FEDERATED_IDENTITY_API, delete_begin, delete_end,
       pattern_predicate);
 
diff --git a/components/capture_mode/camera_video_frame_handler.cc b/components/capture_mode/camera_video_frame_handler.cc
index 6c202887..a786e88 100644
--- a/components/capture_mode/camera_video_frame_handler.cc
+++ b/components/capture_mode/camera_video_frame_handler.cc
@@ -379,10 +379,12 @@
       gpu::GpuMemoryBufferManager* gmb_manager =
           context_factory_->GetGpuMemoryBufferManager();
       for (size_t plane = 0; plane < buffer_planes_.size(); ++plane) {
-        mailboxes_[plane] = shared_image_interface->CreateSharedImage(
+        auto client_shared_image = shared_image_interface->CreateSharedImage(
             gmb.get(), gmb_manager, buffer_planes_[plane],
             frame_info->color_space, kTopLeft_GrSurfaceOrigin,
             kPremul_SkAlphaType, kSharedImageUsage, "CameraVideoFrame");
+        CHECK(client_shared_image);
+        mailboxes_[plane] = client_shared_image->mailbox();
       }
     }
 
diff --git a/components/cast_receiver/browser/BUILD.gn b/components/cast_receiver/browser/BUILD.gn
index e813cbb..137f6c55 100644
--- a/components/cast_receiver/browser/BUILD.gn
+++ b/components/cast_receiver/browser/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 
 if (enable_cast_receiver) {
   source_set("browser") {
diff --git a/components/cast_streaming/features.gni b/components/cast_streaming/features.gni
index 129832e..5b741366 100644
--- a/components/cast_streaming/features.gni
+++ b/components/cast_streaming/features.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 
 declare_args() {
   # Whether the cast remoting feature should be enabled in this build.
diff --git a/components/compose_strings.grdp b/components/compose_strings.grdp
index f7356e2..aecac49 100644
--- a/components/compose_strings.grdp
+++ b/components/compose_strings.grdp
@@ -38,22 +38,22 @@
   Insert
   </message>
   <message name="IDS_COMPOSE_MENU_1_TITLE" desc="The first style menu title." translateable="false">
-  Distance
+  Length
   </message>
   <message name="IDS_COMPOSE_MENU_1_OPTION_1" desc="The first option for the first style." translateable="false">
-  Close
+  Shorten
   </message>
   <message name="IDS_COMPOSE_MENU_1_OPTION_2" desc="The second option for the first style." translateable="false">
-  Far
+  Elaborate
   </message>
   <message name="IDS_COMPOSE_MENU_2_TITLE" desc="The second style menu title." translateable="false">
-  Style
+  Tone
   </message>
   <message name="IDS_COMPOSE_MENU_2_OPTION_1" desc="The first option for the second style." translateable="false">
-  Low
+  Casual
   </message>
   <message name="IDS_COMPOSE_MENU_2_OPTION_2" desc="The second option for the second style." translateable="false">
-  High
+  Formal
   </message>
 
   <!-- Errors -->
diff --git a/components/content_settings/core/browser/content_settings_default_provider.cc b/components/content_settings/core/browser/content_settings_default_provider.cc
index 226720a..2aae4c8 100644
--- a/components/content_settings/core/browser/content_settings_default_provider.cc
+++ b/components/content_settings/core/browser/content_settings_default_provider.cc
@@ -56,6 +56,8 @@
     "profile.default_content_setting_values.ppapi_broker";
 #endif  // !BUILDFLAG(IS_ANDROID)
 #endif  // !BUILDFLAG(IS_IOS)
+constexpr char kObsoleteFederatedIdentityDefaultPref[] =
+    "profile.default_content_setting_values.fedcm_active_session";
 
 ContentSetting GetDefaultValue(const WebsiteSettingsInfo* info) {
   const base::Value& initial_default = info->initial_default_value();
@@ -133,6 +135,7 @@
   registry->RegisterIntegerPref(kObsoletePpapiBrokerDefaultPref, 0);
 #endif  // !BUILDFLAG(IS_ANDROID)
 #endif  // !BUILDFLAG(IS_IOS)
+  registry->RegisterIntegerPref(kObsoleteFederatedIdentityDefaultPref, 0);
 }
 
 DefaultProvider::DefaultProvider(PrefService* prefs,
@@ -335,6 +338,7 @@
   prefs_->ClearPref(kObsoletePpapiBrokerDefaultPref);
 #endif  // !BUILDFLAG(IS_ANDROID)
 #endif  // !BUILDFLAG(IS_IOS)
+  prefs_->ClearPref(kObsoleteFederatedIdentityDefaultPref);
 }
 
 void DefaultProvider::RecordHistogramMetrics() {
diff --git a/components/content_settings/core/browser/content_settings_pref_provider.cc b/components/content_settings/core/browser/content_settings_pref_provider.cc
index 0a1c303e..8f1ad198 100644
--- a/components/content_settings/core/browser/content_settings_pref_provider.cc
+++ b/components/content_settings/core/browser/content_settings_pref_provider.cc
@@ -50,6 +50,8 @@
     kObsoleteGetDisplayMediaSetAutoSelectAllScreensAllowedForUrlsExceptionsPref
         [] = "profile.content_settings.exceptions.get_display_media_set_select_"
              "all_screens";
+constexpr char kObsoleteFederatedIdentityActiveSesssionExceptionsPref[] =
+    "profile.content_settings.exceptions.fedcm_active_session";
 
 }  // namespace
 
@@ -83,6 +85,8 @@
 #endif  // !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID)
   registry->RegisterListPref(
       kObsoleteGetDisplayMediaSetAutoSelectAllScreensAllowedForUrlsExceptionsPref);
+  registry->RegisterListPref(
+      kObsoleteFederatedIdentityActiveSesssionExceptionsPref);
 }
 
 PrefProvider::PrefProvider(PrefService* prefs,
@@ -395,6 +399,7 @@
 #endif  // !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID)
   prefs_->ClearPref(
       kObsoleteGetDisplayMediaSetAutoSelectAllScreensAllowedForUrlsExceptionsPref);
+  prefs_->ClearPref(kObsoleteFederatedIdentityActiveSesssionExceptionsPref);
 }
 
 void PrefProvider::SetClockForTesting(base::Clock* clock) {
diff --git a/components/content_settings/core/browser/content_settings_uma_util.cc b/components/content_settings/core/browser/content_settings_uma_util.cc
index 5b96bb7f..064e3c4 100644
--- a/components/content_settings/core/browser/content_settings_uma_util.cc
+++ b/components/content_settings/core/browser/content_settings_uma_util.cc
@@ -91,7 +91,7 @@
     {ContentSettingsType::JAVASCRIPT_JIT, 79},
     {ContentSettingsType::HTTP_ALLOWED, 80},
     {ContentSettingsType::FORMFILL_METADATA, 81},
-    {ContentSettingsType::FEDERATED_IDENTITY_ACTIVE_SESSION, 82},
+    {ContentSettingsType::DEPRECATED_FEDERATED_IDENTITY_ACTIVE_SESSION, 82},
     {ContentSettingsType::AUTO_DARK_WEB_CONTENT, 83},
     {ContentSettingsType::REQUEST_DESKTOP_SITE, 84},
     {ContentSettingsType::FEDERATED_IDENTITY_API, 85},
diff --git a/components/content_settings/core/browser/website_settings_registry.cc b/components/content_settings/core/browser/website_settings_registry.cc
index 06bb66b..cf19b85 100644
--- a/components/content_settings/core/browser/website_settings_registry.cc
+++ b/components/content_settings/core/browser/website_settings_registry.cc
@@ -243,11 +243,6 @@
            WebsiteSettingsInfo::LOSSY,
            WebsiteSettingsInfo::GENERIC_SINGLE_ORIGIN_SCOPE, ALL_PLATFORMS,
            WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
-  Register(ContentSettingsType::FEDERATED_IDENTITY_ACTIVE_SESSION,
-           "fedcm-active-session", base::Value(),
-           WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
-           WebsiteSettingsInfo::GENERIC_SINGLE_ORIGIN_SCOPE, ALL_PLATFORMS,
-           WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::NOTIFICATION_INTERACTIONS,
            "notification-interactions", base::Value(),
            WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
diff --git a/components/content_settings/core/common/content_settings_types.h b/components/content_settings/core/common/content_settings_types.h
index 8f9c863..a1f8e4c 100644
--- a/components/content_settings/core/common/content_settings_types.h
+++ b/components/content_settings/core/common/content_settings_types.h
@@ -274,7 +274,8 @@
   // a specified account. When this is present it allows access to session
   // management capabilities between the sites. This setting is associated
   // with the relying party's origin.
-  FEDERATED_IDENTITY_ACTIVE_SESSION,
+  // Obsolete on Nov 2023.
+  DEPRECATED_FEDERATED_IDENTITY_ACTIVE_SESSION,
 
   // Setting to indicate whether Chrome should automatically apply darkening to
   // web content.
diff --git a/components/content_settings/renderer/content_settings_agent_impl.cc b/components/content_settings/renderer/content_settings_agent_impl.cc
index c65b17d..69204fe 100644
--- a/components/content_settings/renderer/content_settings_agent_impl.cc
+++ b/components/content_settings/renderer/content_settings_agent_impl.cc
@@ -382,16 +382,6 @@
   return false;
 }
 
-bool ContentSettingsAgentImpl::AllowPopupsAndRedirects(bool default_value) {
-  if (!content_setting_rules_)
-    return default_value;
-  blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
-  return GetContentSettingFromRules(
-             content_setting_rules_->popup_redirect_rules,
-             url::Origin(frame->GetDocument().GetSecurityOrigin()).GetURL()) ==
-         CONTENT_SETTING_ALLOW;
-}
-
 bool ContentSettingsAgentImpl::ShouldAutoupgradeMixedContent() {
   if (mixed_content_autoupgrades_disabled_)
     return false;
@@ -418,6 +408,10 @@
   DidBlockContentType(ContentSettingsType::JAVASCRIPT);
 }
 
+void ContentSettingsAgentImpl::DidNotAllowImage() {
+  DidBlockContentType(ContentSettingsType::IMAGES);
+}
+
 void ContentSettingsAgentImpl::ClearBlockedContentSettings() {
   content_blocked_.clear();
   cached_storage_permissions_.clear();
diff --git a/components/content_settings/renderer/content_settings_agent_impl.h b/components/content_settings/renderer/content_settings_agent_impl.h
index 6073047e..28f178b 100644
--- a/components/content_settings/renderer/content_settings_agent_impl.h
+++ b/components/content_settings/renderer/content_settings_agent_impl.h
@@ -88,10 +88,10 @@
   bool AllowReadFromClipboard(bool default_value) override;
   bool AllowWriteToClipboard(bool default_value) override;
   bool AllowMutationEvents(bool default_value) override;
+  void DidNotAllowImage() override;
   void DidNotAllowScript() override;
   bool AllowRunningInsecureContent(bool allowed_per_settings,
                                    const blink::WebURL& url) override;
-  bool AllowPopupsAndRedirects(bool default_value) override;
   bool ShouldAutoupgradeMixedContent() override;
 
   bool allow_running_insecure_content() const {
diff --git a/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc b/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc
index 488255bc..62c76cc3 100644
--- a/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc
+++ b/components/content_settings/renderer/content_settings_agent_impl_browsertest.cc
@@ -20,6 +20,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/common/navigation/navigation_params.h"
 #include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/test/test_web_frame_content_dumper.h"
@@ -411,28 +412,6 @@
   EXPECT_EQ(1, mock_agent.on_content_blocked_count());
 }
 
-TEST_F(ContentSettingsAgentImplBrowserTest, ContentSettingsAllowScripts) {
-  MockContentSettingsAgentImpl mock_agent(GetMainRenderFrame());
-  // Set the content settings for scripts.
-  RendererContentSettingRules content_setting_rules;
-  ContentSettingsForOneType& script_setting_rules =
-      content_setting_rules.script_rules;
-  script_setting_rules.push_back(ContentSettingPatternSource(
-      ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW),
-      std::string(), false));
-
-  ContentSettingsAgentImpl* agent =
-      ContentSettingsAgentImpl::Get(GetMainRenderFrame());
-  agent->SetRendererContentSettingRulesForTest(content_setting_rules);
-
-  // Load a page which contains a script.
-  LoadHTML(kScriptHtml);
-
-  // Verify that the script was not blocked.
-  EXPECT_EQ(0, mock_agent.on_content_blocked_count());
-}
-
 TEST_F(ContentSettingsAgentImplBrowserTest,
        ContentSettingsAllowScriptsWithSrc) {
   MockContentSettingsAgentImpl mock_agent(GetMainRenderFrame());
@@ -456,103 +435,6 @@
   EXPECT_EQ(0, mock_agent.on_content_blocked_count());
 }
 
-// Regression test for crbug.com/232410: Load a page with JS blocked. Then,
-// allow JS and reload the page. In each case, only one of noscript or script
-// tags should be enabled, but never both.
-TEST_F(ContentSettingsAgentImplBrowserTest, ContentSettingsNoscriptTag) {
-  MockContentSettingsAgentImpl mock_agent(GetMainRenderFrame());
-
-  // 1. Block JavaScript.
-  RendererContentSettingRules content_setting_rules;
-  ContentSettingsForOneType& script_setting_rules =
-      content_setting_rules.script_rules;
-  script_setting_rules.push_back(ContentSettingPatternSource(
-      ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
-      std::string(), false));
-
-  ContentSettingsAgentImpl* agent =
-      ContentSettingsAgentImpl::Get(GetMainRenderFrame());
-  agent->SetRendererContentSettingRulesForTest(content_setting_rules);
-
-  // 2. Load a page which contains a noscript tag and a script tag. Note that
-  // the page doesn't have a body tag.
-  const char kHtml[] =
-      "<html>"
-      "<noscript>JS_DISABLED</noscript>"
-      "<script>document.write('JS_ENABLED');</script>"
-      "</html>";
-  LoadHTML(kHtml);
-  EXPECT_NE(
-      std::string::npos,
-      blink::TestWebFrameContentDumper::DumpLayoutTreeAsText(
-          GetMainFrame(), blink::TestWebFrameContentDumper::kLayoutAsTextNormal)
-          .Utf8()
-          .find("JS_DISABLED"));
-  EXPECT_EQ(
-      std::string::npos,
-      blink::TestWebFrameContentDumper::DumpLayoutTreeAsText(
-          GetMainFrame(), blink::TestWebFrameContentDumper::kLayoutAsTextNormal)
-          .Utf8()
-          .find("JS_ENABLED"));
-
-  // 3. Allow JavaScript.
-  script_setting_rules.clear();
-  script_setting_rules.push_back(ContentSettingPatternSource(
-      ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW),
-      std::string(), false));
-  agent->SetRendererContentSettingRulesForTest(content_setting_rules);
-
-  // 4. Reload the page.
-  std::string url_str = "data:text/html;charset=utf-8,";
-  url_str.append(kHtml);
-  GURL url(url_str);
-  Reload(url);
-  EXPECT_NE(
-      std::string::npos,
-      blink::TestWebFrameContentDumper::DumpLayoutTreeAsText(
-          GetMainFrame(), blink::TestWebFrameContentDumper::kLayoutAsTextNormal)
-          .Utf8()
-          .find("JS_ENABLED"));
-  EXPECT_EQ(
-      std::string::npos,
-      blink::TestWebFrameContentDumper::DumpLayoutTreeAsText(
-          GetMainFrame(), blink::TestWebFrameContentDumper::kLayoutAsTextNormal)
-          .Utf8()
-          .find("JS_DISABLED"));
-}
-
-// Checks that same document navigations don't update content settings for the
-// page.
-TEST_F(ContentSettingsAgentImplBrowserTest,
-       ContentSettingsSameDocumentNavigation) {
-  MockContentSettingsAgentImpl mock_agent(GetMainRenderFrame());
-  // Load a page which contains a script.
-  LoadHTML(kScriptHtml);
-
-  // Verify that the script was not blocked.
-  EXPECT_EQ(0, mock_agent.on_content_blocked_count());
-
-  // Block JavaScript.
-  RendererContentSettingRules content_setting_rules;
-  ContentSettingsForOneType& script_setting_rules =
-      content_setting_rules.script_rules;
-  script_setting_rules.push_back(ContentSettingPatternSource(
-      ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
-      std::string(), false));
-
-  ContentSettingsAgentImpl* agent =
-      ContentSettingsAgentImpl::Get(GetMainRenderFrame());
-  agent->SetRendererContentSettingRulesForTest(content_setting_rules);
-
-  // The page shouldn't see the change to script blocking setting after a
-  // same document navigation.
-  OnSameDocumentNavigation(GetMainFrame(), true);
-  EXPECT_TRUE(agent->AllowScript(true));
-}
-
 TEST_F(ContentSettingsAgentImplBrowserTest, MixedAutoupgradesDisabledByRules) {
   MockContentSettingsAgentImpl mock_agent(GetMainRenderFrame());
 
diff --git a/components/crash/content/browser/BUILD.gn b/components/crash/content/browser/BUILD.gn
index 774f3f50..31ba918 100644
--- a/components/crash/content/browser/BUILD.gn
+++ b/components/crash/content/browser/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 
 if (is_android) {
diff --git a/components/enterprise/buildflags/buildflags.gni b/components/enterprise/buildflags/buildflags.gni
index b26c6ca..90658d1 100644
--- a/components/enterprise/buildflags/buildflags.gni
+++ b/components/enterprise/buildflags/buildflags.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/args.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index f2812a9a..9fdf78a 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -223,8 +223,6 @@
     "test/shell_surface_builder.h",
     "test/surface_tree_host_test_util.cc",
     "test/surface_tree_host_test_util.h",
-    "test/test_data_device_delegate.cc",
-    "test/test_data_device_delegate.h",
     "test/test_security_delegate.cc",
     "test/test_security_delegate.h",
   ]
@@ -320,6 +318,7 @@
     "//components/user_manager",
     "//components/viz/service",
     "//components/viz/test:test_support",
+    "//content/test:test_support",
     "//device/gamepad:test_helpers",
     "//gpu/command_buffer/client:raster_interface",
     "//skia",
@@ -340,7 +339,6 @@
     "//ui/gfx",
     "//ui/gfx:test_support",
     "//ui/gfx/geometry",
-    "//ui/gl:test_support",
     "//ui/message_center",
     "//ui/views",
     "//ui/wm",
diff --git a/components/exo/buffer.cc b/components/exo/buffer.cc
index 27dd90a..6705179 100644
--- a/components/exo/buffer.cc
+++ b/components/exo/buffer.cc
@@ -267,20 +267,22 @@
     usage |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
   }
 
+  scoped_refptr<gpu::ClientSharedImage> client_shared_image;
   if (media::IsMultiPlaneFormatForHardwareVideoEnabled()) {
     auto si_format = GetSharedImageFormat(gpu_memory_buffer_->GetFormat());
-    auto client_shared_image = sii->CreateSharedImage(
+    client_shared_image = sii->CreateSharedImage(
         si_format, gpu_memory_buffer_->GetSize(), color_space,
         kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, usage, "ExoTexture",
         gpu_memory_buffer_->CloneHandle());
-    CHECK(client_shared_image);
-    mailbox_ = client_shared_image->mailbox();
+
   } else {
-    mailbox_ = sii->CreateSharedImage(
+    client_shared_image = sii->CreateSharedImage(
         gpu_memory_buffer_, gpu_memory_buffer_manager,
         gfx::BufferPlane::DEFAULT, color_space, kTopLeft_GrSurfaceOrigin,
         kPremul_SkAlphaType, usage, "ExoTexture");
   }
+  CHECK(client_shared_image);
+  mailbox_ = client_shared_image->mailbox();
   DCHECK(!mailbox_.IsZero());
   gpu::raster::RasterInterface* ri = context_provider_->RasterInterface();
   sync_token_out = sii->GenUnverifiedSyncToken();
diff --git a/components/exo/data_device.cc b/components/exo/data_device.cc
index 62ca151..a58425ae 100644
--- a/components/exo/data_device.cc
+++ b/components/exo/data_device.cc
@@ -52,6 +52,7 @@
 
 DataDevice::DataDevice(DataDeviceDelegate* delegate, Seat* seat)
     : delegate_(delegate), seat_(seat), drop_succeeded_(false) {
+  WMHelper::GetInstance()->AddDragDropObserver(this);
   ui::ClipboardMonitor::GetInstance()->AddObserver(this);
 
   seat_->AddObserver(this, kDataDeviceSeatObserverPriority);
@@ -63,6 +64,7 @@
 DataDevice::~DataDevice() {
   delegate_->OnDataDeviceDestroying(this);
 
+  WMHelper::GetInstance()->RemoveDragDropObserver(this);
   ui::ClipboardMonitor::GetInstance()->RemoveObserver(this);
 
   seat_->RemoveObserver(this);
@@ -138,8 +140,7 @@
   data_offer_.reset();
 }
 
-aura::client::DragDropDelegate::DropCallback DataDevice::GetDropCallback(
-    const ui::DropTargetEvent& event) {
+WMHelper::DragDropObserver::DropCallback DataDevice::GetDropCallback() {
   base::ScopedClosureRunner drag_exit(
       base::BindOnce(&DataDevice::OnDragExited, weak_factory_.GetWeakPtr()));
   return base::BindOnce(&DataDevice::PerformDropOrExitDrag,
@@ -160,28 +161,14 @@
           ? gained_surface
           : nullptr;
   // Check if focused surface is not changed.
-  if ((focused_surface_ && focused_surface_->get() == next_focused_surface) ||
-      (!focused_surface_ && !next_focused_surface)) {
+  if (focused_surface_ && focused_surface_->get() == next_focused_surface)
     return;
-  }
-
-  // Technically speaking, we don't have to reset the delegate on previously
-  // focused window because a surface will not be moved to another application,
-  // which will have its own data device.  This is just for the safety reason.
-  if (focused_surface_ && focused_surface_->get()) {
-    aura::client::SetDragDropDelegate(focused_surface_->get()->window(),
-                                      nullptr);
-  }
 
   std::unique_ptr<ScopedSurface> last_focused_surface =
       std::move(focused_surface_);
-
   focused_surface_ = next_focused_surface ? std::make_unique<ScopedSurface>(
                                                 next_focused_surface, this)
                                           : nullptr;
-  if (focused_surface_) {
-    aura::client::SetDragDropDelegate(focused_surface_->get()->window(), this);
-  }
 
   // Check if the client newly obtained focus.
   if (focused_surface_ && !last_focused_surface)
@@ -227,9 +214,7 @@
 
 void DataDevice::PerformDropOrExitDrag(
     base::ScopedClosureRunner exit_drag,
-    std::unique_ptr<ui::OSExchangeData> data,
-    ui::mojom::DragOperation& output_drag_op,
-    std::unique_ptr<ui::LayerTreeOwner> drag_image_layer_owner) {
+    ui::mojom::DragOperation& output_drag_op) {
   exit_drag.ReplaceClosure(base::DoNothing());
 
   if (!data_offer_) {
diff --git a/components/exo/data_device.h b/components/exo/data_device.h
index 30e4765..999f43c 100644
--- a/components/exo/data_device.h
+++ b/components/exo/data_device.h
@@ -13,8 +13,6 @@
 #include "components/exo/seat_observer.h"
 #include "components/exo/surface.h"
 #include "components/exo/surface_observer.h"
-#include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/base/clipboard/clipboard_observer.h"
 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
 
@@ -33,9 +31,9 @@
 
 enum class DndAction { kNone, kCopy, kMove, kAsk };
 
-// DataDevice to start drag and drop and copy and paste operations.
-class DataDevice : public DataOfferObserver,
-                   public aura::client::DragDropDelegate,
+// DataDevice to start drag and drop and copy and paste oprations.
+class DataDevice : public WMHelper::DragDropObserver,
+                   public DataOfferObserver,
                    public ui::ClipboardObserver,
                    public SurfaceObserver,
                    public SeatObserver {
@@ -62,13 +60,12 @@
   // |source| represents data comes from the client.
   void SetSelection(DataSource* source);
 
-  // aura::client::DragDropDelegate:
+  // Overridden from WMHelper::DragDropObserver:
   void OnDragEntered(const ui::DropTargetEvent& event) override;
   aura::client::DragUpdateInfo OnDragUpdated(
       const ui::DropTargetEvent& event) override;
   void OnDragExited() override;
-  aura::client::DragDropDelegate::DropCallback GetDropCallback(
-      const ui::DropTargetEvent& event) override;
+  WMHelper::DragDropObserver::DropCallback GetDropCallback() override;
 
   // Overridden from ui::ClipboardObserver:
   void OnClipboardDataChanged() override;
@@ -90,11 +87,8 @@
   Surface* GetEffectiveTargetForEvent(const ui::DropTargetEvent& event) const;
   void SetSelectionToCurrentClipboardData();
 
-  void PerformDropOrExitDrag(
-      base::ScopedClosureRunner exit_drag,
-      std::unique_ptr<ui::OSExchangeData> data,
-      ui::mojom::DragOperation& output_drag_op,
-      std::unique_ptr<ui::LayerTreeOwner> drag_image_layer_owner);
+  void PerformDropOrExitDrag(base::ScopedClosureRunner exit_drag,
+                             ui::mojom::DragOperation& output_drag_op);
 
   const raw_ptr<DataDeviceDelegate, DanglingUntriaged | ExperimentalAsh>
       delegate_;
diff --git a/components/exo/data_device_unittest.cc b/components/exo/data_device_unittest.cc
index 809732c9..686d5964 100644
--- a/components/exo/data_device_unittest.cc
+++ b/components/exo/data_device_unittest.cc
@@ -15,7 +15,12 @@
 #include "base/task/single_thread_task_runner.h"
 #include "base/test/bind.h"
 #include "chromeos/ui/base/window_properties.h"
+#include "components/exo/data_device_delegate.h"
 #include "components/exo/data_exchange_delegate.h"
+#include "components/exo/data_offer.h"
+#include "components/exo/data_offer_delegate.h"
+#include "components/exo/data_source.h"
+#include "components/exo/data_source_delegate.h"
 #include "components/exo/extended_drag_source.h"
 #include "components/exo/seat.h"
 #include "components/exo/shell_surface.h"
@@ -23,8 +28,9 @@
 #include "components/exo/surface_delegate.h"
 #include "components/exo/test/exo_test_base.h"
 #include "components/exo/test/exo_test_data_exchange_delegate.h"
+#include "components/exo/test/exo_test_helper.h"
 #include "components/exo/test/shell_surface_builder.h"
-#include "components/exo/test/test_data_device_delegate.h"
+#include "ui/aura/client/focus_client.h"
 #include "ui/base/clipboard/scoped_clipboard_writer.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/dragdrop/drop_target_event.h"
@@ -37,6 +43,86 @@
 
 using ::ui::mojom::DragOperation;
 
+enum class DataEvent {
+  kOffer,
+  kEnter,
+  kLeave,
+  kMotion,
+  kDrop,
+  kDestroy,
+  kSelection
+};
+
+class TestDataOfferDelegate : public DataOfferDelegate {
+ public:
+  ~TestDataOfferDelegate() override {}
+
+  // Overridden from DataOfferDelegate:
+  void OnDataOfferDestroying(DataOffer* offer) override { delete this; }
+  void OnOffer(const std::string& mime_type) override {}
+  void OnSourceActions(
+      const base::flat_set<DndAction>& source_actions) override {}
+  void OnAction(DndAction action) override {}
+};
+
+class TestDataDeviceDelegate : public DataDeviceDelegate {
+ public:
+  TestDataDeviceDelegate() {}
+
+  TestDataDeviceDelegate(const TestDataDeviceDelegate&) = delete;
+  TestDataDeviceDelegate& operator=(const TestDataDeviceDelegate&) = delete;
+
+  size_t PopEvents(std::vector<DataEvent>* out) {
+    out->swap(events_);
+    events_.clear();
+    return out->size();
+  }
+  Surface* entered_surface() const { return entered_surface_; }
+  void DeleteDataOffer(bool finished) {
+    if (finished)
+      data_offer_->Finish();
+    data_offer_.reset();
+  }
+  void set_can_accept_data_events_for_surface(bool value) {
+    can_accept_data_events_for_surface_ = value;
+  }
+
+  // Overridden from DataDeviceDelegate:
+  void OnDataDeviceDestroying(DataDevice* data_device) override {
+    events_.push_back(DataEvent::kDestroy);
+  }
+  DataOffer* OnDataOffer() override {
+    events_.push_back(DataEvent::kOffer);
+    data_offer_ = std::make_unique<DataOffer>(new TestDataOfferDelegate);
+    return data_offer_.get();
+  }
+  void OnEnter(Surface* surface,
+               const gfx::PointF& location,
+               const DataOffer& data_offer) override {
+    events_.push_back(DataEvent::kEnter);
+    entered_surface_ = surface;
+  }
+  void OnLeave() override { events_.push_back(DataEvent::kLeave); }
+  void OnMotion(base::TimeTicks time_stamp,
+                const gfx::PointF& location) override {
+    events_.push_back(DataEvent::kMotion);
+  }
+  void OnDrop() override { events_.push_back(DataEvent::kDrop); }
+  void OnSelection(const DataOffer& data_offer) override {
+    events_.push_back(DataEvent::kSelection);
+  }
+  bool CanAcceptDataEventsForSurface(Surface* surface) const override {
+    return can_accept_data_events_for_surface_;
+  }
+
+ private:
+  std::vector<DataEvent> events_;
+  std::unique_ptr<DataOffer> data_offer_;
+  raw_ptr<Surface, DanglingUntriaged | ExperimentalAsh> entered_surface_ =
+      nullptr;
+  bool can_accept_data_events_for_surface_ = true;
+};
+
 class TestSeat : public Seat {
  public:
   TestSeat() : Seat(std::make_unique<TestDataExchangeDelegate>()) {}
@@ -71,22 +157,18 @@
   }
 
  protected:
-  test::TestDataDeviceDelegate delegate_;
+  TestDataDeviceDelegate delegate_;
   std::unique_ptr<TestSeat> seat_;
   std::unique_ptr<DataDevice> device_;
   ui::OSExchangeData data_;
   std::unique_ptr<Surface> surface_;
-
-  const ui::OSExchangeData unused_data_;
-  const ui::DropTargetEvent unused_drop_target_event_{
-      unused_data_, gfx::PointF(), gfx::PointF(), 0};
 };
 
 TEST_F(DataDeviceTest, Destroy) {
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   device_.reset();
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kDestroy, events[0]);
+  EXPECT_EQ(DataEvent::kDestroy, events[0]);
 }
 
 TEST_F(DataDeviceTest, DataEventsDrop) {
@@ -94,27 +176,27 @@
                             ui::DragDropTypes::DRAG_MOVE);
   ui::Event::DispatcherApi(&event).set_target(surface_->window());
 
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   device_->OnDragEntered(event);
   ASSERT_EQ(2u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kOffer, events[0]);
-  EXPECT_EQ(test::DataEvent::kEnter, events[1]);
+  EXPECT_EQ(DataEvent::kOffer, events[0]);
+  EXPECT_EQ(DataEvent::kEnter, events[1]);
 
   EXPECT_EQ(ui::DragDropTypes::DRAG_LINK,
             device_->OnDragUpdated(event).drag_operation);
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kMotion, events[0]);
+  EXPECT_EQ(DataEvent::kMotion, events[0]);
 
   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(&test::TestDataDeviceDelegate::DeleteDataOffer,
+      FROM_HERE, base::BindOnce(&TestDataDeviceDelegate::DeleteDataOffer,
                                 base::Unretained(&delegate_), true));
-  auto drop_cb = device_->GetDropCallback(unused_drop_target_event_);
+
+  auto drop_cb = device_->GetDropCallback();
   DragOperation output_drag_op;
-  std::move(drop_cb).Run(/*data=*/nullptr, output_drag_op,
-                         /*drag_image_layer_owner=*/nullptr);
+  std::move(drop_cb).Run(output_drag_op);
   EXPECT_EQ(DragOperation::kLink, output_drag_op);
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kDrop, events[0]);
+  EXPECT_EQ(DataEvent::kDrop, events[0]);
 }
 
 TEST_F(DataDeviceTest, DataEventsExit) {
@@ -122,20 +204,20 @@
                             ui::DragDropTypes::DRAG_MOVE);
   ui::Event::DispatcherApi(&event).set_target(surface_->window());
 
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   device_->OnDragEntered(event);
   ASSERT_EQ(2u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kOffer, events[0]);
-  EXPECT_EQ(test::DataEvent::kEnter, events[1]);
+  EXPECT_EQ(DataEvent::kOffer, events[0]);
+  EXPECT_EQ(DataEvent::kEnter, events[1]);
 
   EXPECT_EQ(ui::DragDropTypes::DRAG_LINK,
             device_->OnDragUpdated(event).drag_operation);
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kMotion, events[0]);
+  EXPECT_EQ(DataEvent::kMotion, events[0]);
 
   device_->OnDragExited();
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kLeave, events[0]);
+  EXPECT_EQ(DataEvent::kLeave, events[0]);
 }
 
 TEST_F(DataDeviceTest, DeleteDataDeviceDuringDrop) {
@@ -145,10 +227,9 @@
   device_->OnDragEntered(event);
   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
       FROM_HERE, base::BindLambdaForTesting([&]() { device_.reset(); }));
-  auto drop_cb = device_->GetDropCallback(unused_drop_target_event_);
+  auto drop_cb = device_->GetDropCallback();
   DragOperation output_drag_op;
-  std::move(drop_cb).Run(/*data=*/nullptr, output_drag_op,
-                         /*drag_image_layer_owner=*/nullptr);
+  std::move(drop_cb).Run(output_drag_op);
   EXPECT_EQ(DragOperation::kNone, output_drag_op);
 }
 
@@ -157,11 +238,11 @@
                             ui::DragDropTypes::DRAG_MOVE);
   ui::Event::DispatcherApi(&event).set_target(surface_->window());
 
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   device_->OnDragEntered(event);
   ASSERT_EQ(2u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kOffer, events[0]);
-  EXPECT_EQ(test::DataEvent::kEnter, events[1]);
+  EXPECT_EQ(DataEvent::kOffer, events[0]);
+  EXPECT_EQ(DataEvent::kEnter, events[1]);
 
   delegate_.DeleteDataOffer(false);
 
@@ -169,10 +250,9 @@
             device_->OnDragUpdated(event).drag_operation);
   EXPECT_EQ(0u, delegate_.PopEvents(&events));
 
-  auto drop_cb = device_->GetDropCallback(unused_drop_target_event_);
+  auto drop_cb = device_->GetDropCallback();
   DragOperation output_drag_op;
-  std::move(drop_cb).Run(/*data=*/nullptr, output_drag_op,
-                         /*drag_image_layer_owner=*/nullptr);
+  std::move(drop_cb).Run(output_drag_op);
   EXPECT_EQ(0u, delegate_.PopEvents(&events));
 }
 
@@ -181,28 +261,27 @@
                             ui::DragDropTypes::DRAG_MOVE);
   ui::Event::DispatcherApi(&event).set_target(surface_->window());
 
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   device_->OnDragEntered(event);
   ASSERT_EQ(2u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kOffer, events[0]);
-  EXPECT_EQ(test::DataEvent::kEnter, events[1]);
+  EXPECT_EQ(DataEvent::kOffer, events[0]);
+  EXPECT_EQ(DataEvent::kEnter, events[1]);
 
   EXPECT_EQ(ui::DragDropTypes::DRAG_LINK,
             device_->OnDragUpdated(event).drag_operation);
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kMotion, events[0]);
+  EXPECT_EQ(DataEvent::kMotion, events[0]);
 
   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(&test::TestDataDeviceDelegate::DeleteDataOffer,
+      FROM_HERE, base::BindOnce(&TestDataDeviceDelegate::DeleteDataOffer,
                                 base::Unretained(&delegate_), false));
 
-  auto drop_cb = device_->GetDropCallback(unused_drop_target_event_);
+  auto drop_cb = device_->GetDropCallback();
   DragOperation output_drag_op;
-  std::move(drop_cb).Run(/*data=*/nullptr, output_drag_op,
-                         /*drag_image_layer_owner=*/nullptr);
+  std::move(drop_cb).Run(output_drag_op);
   EXPECT_EQ(DragOperation::kNone, output_drag_op);
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kDrop, events[0]);
+  EXPECT_EQ(DataEvent::kDrop, events[0]);
 }
 
 TEST_F(DataDeviceTest, NotAcceptDataEventsForSurface) {
@@ -210,7 +289,7 @@
                             ui::DragDropTypes::DRAG_MOVE);
   ui::Event::DispatcherApi(&event).set_target(surface_->window());
 
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   delegate_.set_can_accept_data_events_for_surface(false);
 
   device_->OnDragEntered(event);
@@ -220,10 +299,9 @@
             device_->OnDragUpdated(event).drag_operation);
   EXPECT_EQ(0u, delegate_.PopEvents(&events));
 
-  auto drop_cb = device_->GetDropCallback(unused_drop_target_event_);
+  auto drop_cb = device_->GetDropCallback();
   DragOperation output_drag_op;
-  std::move(drop_cb).Run(/*data=*/nullptr, output_drag_op,
-                         /*drag_image_layer_owner=*/nullptr);
+  std::move(drop_cb).Run(output_drag_op);
   EXPECT_EQ(0u, delegate_.PopEvents(&events));
 }
 
@@ -232,30 +310,29 @@
                             ui::DragDropTypes::DRAG_MOVE);
   ui::Event::DispatcherApi(&event).set_target(surface_->window());
 
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   device_->OnDragEntered(event);
   ASSERT_EQ(2u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kOffer, events[0]);
-  EXPECT_EQ(test::DataEvent::kEnter, events[1]);
+  EXPECT_EQ(DataEvent::kOffer, events[0]);
+  EXPECT_EQ(DataEvent::kEnter, events[1]);
 
   EXPECT_EQ(ui::DragDropTypes::DRAG_LINK,
             device_->OnDragUpdated(event).drag_operation);
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kMotion, events[0]);
+  EXPECT_EQ(DataEvent::kMotion, events[0]);
 
-  auto drop_cb = device_->GetDropCallback(unused_drop_target_event_);
+  auto drop_cb = device_->GetDropCallback();
 
   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(&test::TestDataDeviceDelegate::DeleteDataOffer,
+      FROM_HERE, base::BindOnce(&TestDataDeviceDelegate::DeleteDataOffer,
                                 base::Unretained(&delegate_), true));
 
   DragOperation output_drag_op = DragOperation::kNone;
-  std::move(drop_cb).Run(/*data=*/nullptr, output_drag_op,
-                         /*drag_image_layer_owner=*/nullptr);
+  std::move(drop_cb).Run(output_drag_op);
 
   EXPECT_EQ(DragOperation::kLink, output_drag_op);
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kDrop, events[0]);
+  EXPECT_EQ(DataEvent::kDrop, events[0]);
 }
 
 TEST_F(DataDeviceTest, DropCallback_Invalidated) {
@@ -263,24 +340,23 @@
                             ui::DragDropTypes::DRAG_MOVE);
   ui::Event::DispatcherApi(&event).set_target(surface_->window());
 
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   device_->OnDragEntered(event);
   ASSERT_EQ(2u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kOffer, events[0]);
-  EXPECT_EQ(test::DataEvent::kEnter, events[1]);
+  EXPECT_EQ(DataEvent::kOffer, events[0]);
+  EXPECT_EQ(DataEvent::kEnter, events[1]);
 
   EXPECT_EQ(ui::DragDropTypes::DRAG_LINK,
             device_->OnDragUpdated(event).drag_operation);
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kMotion, events[0]);
+  EXPECT_EQ(DataEvent::kMotion, events[0]);
 
-  auto drop_cb = device_->GetDropCallback(unused_drop_target_event_);
+  auto drop_cb = device_->GetDropCallback();
 
   delegate_.DeleteDataOffer(false);
 
   DragOperation output_drag_op = DragOperation::kNone;
-  std::move(drop_cb).Run(/*data=*/nullptr, output_drag_op,
-                         /*drag_image_layer_owner=*/nullptr);
+  std::move(drop_cb).Run(output_drag_op);
 
   EXPECT_EQ(DragOperation::kNone, output_drag_op);
   EXPECT_EQ(0u, delegate_.PopEvents(&events));
@@ -291,31 +367,31 @@
                             ui::DragDropTypes::DRAG_MOVE);
   ui::Event::DispatcherApi(&event).set_target(surface_->window());
 
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   device_->OnDragEntered(event);
   ASSERT_EQ(2u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kOffer, events[0]);
-  EXPECT_EQ(test::DataEvent::kEnter, events[1]);
+  EXPECT_EQ(DataEvent::kOffer, events[0]);
+  EXPECT_EQ(DataEvent::kEnter, events[1]);
 
   EXPECT_EQ(ui::DragDropTypes::DRAG_LINK,
             device_->OnDragUpdated(event).drag_operation);
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kMotion, events[0]);
+  EXPECT_EQ(DataEvent::kMotion, events[0]);
 
-  auto drop_cb = device_->GetDropCallback(unused_drop_target_event_);
+  auto drop_cb = device_->GetDropCallback();
   drop_cb.Reset();
 
   ASSERT_EQ(1u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kLeave, events[0]);
+  EXPECT_EQ(DataEvent::kLeave, events[0]);
 }
 
 TEST_F(DataDeviceTest, ClipboardCopy) {
   // Selection event sent when getting a focus.
   device_->OnSurfaceFocused(surface_.get(), nullptr, true);
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   ASSERT_EQ(2u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kOffer, events[0]);
-  EXPECT_EQ(test::DataEvent::kSelection, events[1]);
+  EXPECT_EQ(DataEvent::kOffer, events[0]);
+  EXPECT_EQ(DataEvent::kSelection, events[1]);
 
   // Next focus does not send selection.
   device_->OnSurfaceFocused(surface_.get(), nullptr, true);
@@ -324,8 +400,8 @@
   // Clipboard change
   device_->OnClipboardDataChanged();
   ASSERT_EQ(2u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kOffer, events[0]);
-  EXPECT_EQ(test::DataEvent::kSelection, events[1]);
+  EXPECT_EQ(DataEvent::kOffer, events[0]);
+  EXPECT_EQ(DataEvent::kSelection, events[1]);
 
   // Losing focus does not create events.
   device_->OnSurfaceFocused(nullptr, nullptr, true);
@@ -334,27 +410,27 @@
 
 TEST_F(DataDeviceTest, ClipboardCopyWithoutFocus) {
   device_->OnClipboardDataChanged();
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   EXPECT_EQ(0u, delegate_.PopEvents(&events));
 }
 
 TEST_F(DataDeviceTest, ClipboardDeviceCreatedAfterFocus) {
   seat_->set_focused_surface(surface_.get());
   device_.reset();
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   delegate_.PopEvents(&events);
 
   device_ = std::make_unique<DataDevice>(&delegate_, seat_.get());
 
   ASSERT_EQ(2u, delegate_.PopEvents(&events));
-  EXPECT_EQ(test::DataEvent::kOffer, events[0]);
-  EXPECT_EQ(test::DataEvent::kSelection, events[1]);
+  EXPECT_EQ(DataEvent::kOffer, events[0]);
+  EXPECT_EQ(DataEvent::kSelection, events[1]);
 }
 
 TEST_F(DataDeviceTest, ClipboardFocusedSurfaceDestroyed) {
   device_->OnSurfaceFocused(surface_.get(), nullptr, true);
   surface_.reset();
-  std::vector<test::DataEvent> events;
+  std::vector<DataEvent> events;
   delegate_.PopEvents(&events);
 
   device_->OnClipboardDataChanged();
diff --git a/components/exo/extended_drag_source_unittest.cc b/components/exo/extended_drag_source_unittest.cc
index d21de0f..117b952 100644
--- a/components/exo/extended_drag_source_unittest.cc
+++ b/components/exo/extended_drag_source_unittest.cc
@@ -31,7 +31,6 @@
 #include "components/exo/test/exo_test_data_exchange_delegate.h"
 #include "components/exo/test/exo_test_helper.h"
 #include "components/exo/test/shell_surface_builder.h"
-#include "components/exo/test/test_data_device_delegate.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/client/aura_constants.h"
@@ -124,8 +123,6 @@
 
     seat_ =
         std::make_unique<Seat>(std::make_unique<TestDataExchangeDelegate>());
-    data_device_ =
-        std::make_unique<DataDevice>(&data_device_delegate_, seat_.get());
     data_source_delegate_ = std::make_unique<TestDataSourceDelegate>();
     data_source_ = std::make_unique<DataSource>(data_source_delegate_.get());
     extended_drag_source_ = std::make_unique<ExtendedDragSource>(
@@ -138,7 +135,6 @@
     extended_drag_source_.reset();
     data_source_.reset();
     data_source_delegate_.reset();
-    data_device_.reset();
     seat_.reset();
     test::ExoTestBase::TearDown();
   }
@@ -168,8 +164,6 @@
   std::unique_ptr<DataSource> data_source_;
   std::unique_ptr<ExtendedDragSource> extended_drag_source_;
   std::unique_ptr<TestDataSourceDelegate> data_source_delegate_;
-  test::TestDataDeviceDelegate data_device_delegate_;
-  std::unique_ptr<DataDevice> data_device_;
 };
 
 }  // namespace
@@ -179,8 +173,8 @@
 
   // Give |origin| a root window and start DragDropOperation.
   GetContext()->AddChild(origin.window());
-  data_device_->StartDrag(data_source_.get(), &origin,
-                          /*icon=*/nullptr, ui::mojom::DragEventSource::kMouse);
+  seat_->StartDrag(data_source_.get(), &origin,
+                   /*icon=*/nullptr, ui::mojom::DragEventSource::kMouse);
 
   // Ensure that destroying the data source invalidates its extended_drag_source
   // counterpart for the rest of its lifetime.
@@ -573,8 +567,8 @@
 
   // Start a DragDropOperation.
   drag_drop_controller_->set_should_block_during_drag_drop(true);
-  data_device_->StartDrag(data_source_.get(), surface, /*icon=*/nullptr,
-                          ui::mojom::DragEventSource::kMouse);
+  seat_->StartDrag(data_source_.get(), surface, /*icon=*/nullptr,
+                   ui::mojom::DragEventSource::kMouse);
 
   auto task_1 = base::BindLambdaForTesting([&]() {
     generator.MoveMouseBy(190, 190);
@@ -646,8 +640,8 @@
 
   // Start a DragDropOperation.
   drag_drop_controller_->set_should_block_during_drag_drop(true);
-  data_device_->StartDrag(data_source_.get(), origin_surface, /*icon=*/nullptr,
-                          ui::mojom::DragEventSource::kTouch);
+  seat_->StartDrag(data_source_.get(), origin_surface, /*icon=*/nullptr,
+                   ui::mojom::DragEventSource::kTouch);
 
   base::RunLoop loop;
   drag_drop_controller_->SetLoopClosureForTesting(
@@ -722,8 +716,8 @@
   // Start a DragDropOperation.
   drag_drop_controller_->set_should_block_during_drag_drop(true);
 
-  data_device_->StartDrag(data_source_.get(), origin_surface, /*icon=*/nullptr,
-                          ui::mojom::DragEventSource::kMouse);
+  seat_->StartDrag(data_source_.get(), origin_surface, /*icon=*/nullptr,
+                   ui::mojom::DragEventSource::kMouse);
   // Just move to the middle to avoid snapping.
   int x_movement = 300;
 
diff --git a/components/exo/pointer_unittest.cc b/components/exo/pointer_unittest.cc
index 644bf08..f73cf7d 100644
--- a/components/exo/pointer_unittest.cc
+++ b/components/exo/pointer_unittest.cc
@@ -36,7 +36,6 @@
 #include "components/exo/test/exo_test_helper.h"
 #include "components/exo/test/shell_surface_builder.h"
 #include "components/exo/test/surface_tree_host_test_util.h"
-#include "components/exo/test/test_data_device_delegate.h"
 #include "components/exo/wm_helper.h"
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/service/surfaces/surface.h"
@@ -204,26 +203,14 @@
         switches::kEnablePixelOutputInTests);
 
     test::ExoTestBase::SetUp();
-    seat_ =
-        std::make_unique<Seat>(std::make_unique<TestDataExchangeDelegate>());
-    data_device_ =
-        std::make_unique<DataDevice>(&data_device_delegate_, seat_.get());
-
-    // TODO(oshima): This is no longer necessary. Remove this.
+    // Sometimes underlying infra (i.e. X11 / Xvfb) may emit pointer events
+    // which can break MockPointerDelegate's expectations, so they should be
+    // consumed before starting. See https://crbug.com/854674.
     base::RunLoop().RunUntilIdle();
   }
 
-  void TearDown() override {
-    data_device_.reset();
-    seat_.reset();
-    test::ExoTestBase::TearDown();
-  }
-
- protected:
+ private:
   base::test::ScopedFeatureList feature_list_;
-  std::unique_ptr<Seat> seat_;
-  test::TestDataDeviceDelegate data_device_delegate_;
-  std::unique_ptr<DataDevice> data_device_;
 };
 
 class PointerConstraintTest : public PointerTest {
@@ -237,6 +224,7 @@
 
     shell_surface_ = BuildShellSurfaceWhichPermitsPointerLock();
     surface_ = shell_surface_->surface_for_testing();
+    seat_ = std::make_unique<Seat>();
     pointer_ = std::make_unique<Pointer>(&delegate_, seat_.get());
 
     focus_client_ =
@@ -255,6 +243,7 @@
 
   void TearDown() override {
     // Many objects need to be destroyed before teardown for various reasons.
+    seat_.reset();
     shell_surface_.reset();
     surface_ = nullptr;
 
@@ -276,6 +265,7 @@
 
   std::unique_ptr<ui::test::EventGenerator> generator_;
   std::unique_ptr<Pointer> pointer_;
+  std::unique_ptr<Seat> seat_;
   testing::NiceMock<MockPointerConstraintDelegate> constraint_delegate_;
   testing::NiceMock<MockPointerDelegate> delegate_;
   std::unique_ptr<ShellSurface> shell_surface_;
@@ -303,8 +293,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
-
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -364,7 +354,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -389,7 +380,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -442,7 +434,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -468,7 +461,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -530,7 +524,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -566,7 +561,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -584,7 +580,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -611,7 +608,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -678,7 +676,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -703,7 +702,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -731,7 +731,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
   gfx::Point location = surface->window()->GetBoundsInScreen().origin();
 
@@ -761,7 +762,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
   gfx::Point location = surface->window()->GetBoundsInScreen().origin();
 
@@ -791,7 +793,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -824,7 +827,8 @@
   EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen());
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, OnPointerFrame()).Times(testing::AnyNumber());
@@ -876,7 +880,8 @@
   EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen());
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, OnPointerFrame()).Times(testing::AnyNumber());
@@ -934,7 +939,8 @@
   EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen());
 
   MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, OnPointerFrame()).Times(testing::AnyNumber());
@@ -974,7 +980,8 @@
   auto* surface2 = shell_surface2->surface_for_testing();
 
   MockPointerDelegate delegate;
-  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, seat_.get()));
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   EXPECT_CALL(delegate, OnPointerFrame()).Times(testing::AnyNumber());
@@ -1019,8 +1026,9 @@
 }
 
 TEST_P(PointerTest, DragDropAbortBeforeStart) {
-  MockPointerDelegate delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat(std::make_unique<TestDataExchangeDelegate>());
+  MockPointerDelegate pointer_delegate;
+  std::unique_ptr<Pointer> pointer(new Pointer(&pointer_delegate, &seat));
   TestDataSourceDelegate data_source_delegate;
   DataSource source(&data_source_delegate);
 
@@ -1029,30 +1037,30 @@
 
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(origin))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(origin))
       .WillRepeatedly(testing::Return(true));
-  EXPECT_CALL(delegate, OnPointerFrame()).Times(3);
-  EXPECT_CALL(delegate, OnPointerEnter(origin, gfx::PointF(), 0));
+  EXPECT_CALL(pointer_delegate, OnPointerFrame()).Times(3);
+  EXPECT_CALL(pointer_delegate, OnPointerEnter(origin, gfx::PointF(), 0));
   generator.MoveMouseTo(origin->window()->GetBoundsInScreen().origin());
 
   Surface icon;
-  data_device_->StartDrag(&source, origin, &icon,
-                          ui::mojom::DragEventSource::kMouse);
-  EXPECT_TRUE(seat_->get_drag_drop_operation_for_testing());
+  seat.StartDrag(&source, origin, &icon, ui::mojom::DragEventSource::kMouse);
+  EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
 
-  EXPECT_CALL(delegate, OnPointerButton).Times(2);
+  EXPECT_CALL(pointer_delegate, OnPointerButton).Times(2);
   generator.PressLeftButton();
-  EXPECT_TRUE(seat_->get_drag_drop_operation_for_testing());
+  EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
   generator.ReleaseLeftButton();
-  EXPECT_FALSE(seat_->get_drag_drop_operation_for_testing());
+  EXPECT_FALSE(seat.get_drag_drop_operation_for_testing());
 
-  EXPECT_CALL(delegate, OnPointerDestroying(pointer.get()));
+  EXPECT_CALL(pointer_delegate, OnPointerDestroying(pointer.get()));
   pointer.reset();
 }
 
 TEST_P(PointerTest, DragDropAndPointerEnterLeaveEvents) {
-  MockPointerDelegate delegate;
-  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, seat_.get()));
+  Seat seat(std::make_unique<TestDataExchangeDelegate>());
+  MockPointerDelegate pointer_delegate;
+  std::unique_ptr<Pointer> pointer(new Pointer(&pointer_delegate, &seat));
   TestDataSourceDelegate data_source_delegate;
   DataSource source(&data_source_delegate);
 
@@ -1061,10 +1069,10 @@
 
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(origin))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(origin))
       .WillRepeatedly(testing::Return(true));
-  EXPECT_CALL(delegate, OnPointerFrame()).Times(AnyNumber());
-  EXPECT_CALL(delegate, OnPointerEnter(origin, gfx::PointF(), 0));
+  EXPECT_CALL(pointer_delegate, OnPointerFrame()).Times(AnyNumber());
+  EXPECT_CALL(pointer_delegate, OnPointerEnter(origin, gfx::PointF(), 0));
   generator.MoveMouseTo(origin->window()->GetBoundsInScreen().origin());
 
   auto* drag_drop_controller = static_cast<ash::DragDropController*>(
@@ -1072,9 +1080,9 @@
   ASSERT_TRUE(drag_drop_controller);
 
   generator.PressLeftButton();
-  data_device_->StartDrag(&source, origin, /*icon=*/nullptr,
-                          ui::mojom::DragEventSource::kMouse);
-  EXPECT_TRUE(seat_->get_drag_drop_operation_for_testing());
+  seat.StartDrag(&source, origin, /*icon=*/nullptr,
+                 ui::mojom::DragEventSource::kMouse);
+  EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
 
   // As soon as the runloop gets triggered, emit a mouse release event.
   drag_drop_controller->SetLoopClosureForTesting(
@@ -1091,22 +1099,23 @@
       base::DoNothing());
 
   // Pointer leave should be called only once upon start.
-  EXPECT_CALL(delegate, OnPointerLeave(_)).Times(1);
-  EXPECT_CALL(delegate, OnPointerEnter(_, _, _)).Times(0);
-  EXPECT_CALL(delegate, OnPointerButton(testing::_, testing::_, testing::_))
+  EXPECT_CALL(pointer_delegate, OnPointerLeave(_)).Times(1);
+  EXPECT_CALL(pointer_delegate, OnPointerEnter(_, _, _)).Times(0);
+  EXPECT_CALL(pointer_delegate,
+              OnPointerButton(testing::_, testing::_, testing::_))
       .Times(0);
 
   base::RunLoop().RunUntilIdle();
-  ::testing::Mock::VerifyAndClearExpectations(&delegate);
+  ::testing::Mock::VerifyAndClearExpectations(&pointer_delegate);
 
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(origin))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(origin))
       .WillRepeatedly(testing::Return(true));
-  EXPECT_FALSE(seat_->get_drag_drop_operation_for_testing());
+  EXPECT_FALSE(seat.get_drag_drop_operation_for_testing());
 
   // Pointer leave should be called again after drag and drop.
-  EXPECT_CALL(delegate, OnPointerEnter(_, _, _));
+  EXPECT_CALL(pointer_delegate, OnPointerEnter(_, _, _));
 
-  EXPECT_CALL(delegate, OnPointerDestroying(pointer.get()));
+  EXPECT_CALL(pointer_delegate, OnPointerDestroying(pointer.get()));
 
   generator.MoveMouseBy(1, 1);
 
@@ -1114,8 +1123,9 @@
 }
 
 TEST_P(PointerTest, DragDropAndPointerEnterLeaveEvents_NoOpOnTouchDrag) {
-  MockPointerDelegate delegate;
-  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, seat_.get()));
+  Seat seat(std::make_unique<TestDataExchangeDelegate>());
+  MockPointerDelegate pointer_delegate;
+  std::unique_ptr<Pointer> pointer(new Pointer(&pointer_delegate, &seat));
   TestDataSourceDelegate data_source_delegate;
   DataSource source(&data_source_delegate);
 
@@ -1124,19 +1134,19 @@
 
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(origin))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(origin))
       .WillRepeatedly(testing::Return(true));
-  EXPECT_CALL(delegate, OnPointerFrame()).Times(AnyNumber());
-  EXPECT_CALL(delegate, OnPointerEnter(origin, gfx::PointF(), 0));
+  EXPECT_CALL(pointer_delegate, OnPointerFrame()).Times(AnyNumber());
+  EXPECT_CALL(pointer_delegate, OnPointerEnter(origin, gfx::PointF(), 0));
   generator.MoveMouseTo(origin->window()->GetBoundsInScreen().origin());
 
   auto* drag_drop_controller = static_cast<ash::DragDropController*>(
       aura::client::GetDragDropClient(ash::Shell::GetPrimaryRootWindow()));
   ASSERT_TRUE(drag_drop_controller);
 
-  data_device_->StartDrag(&source, origin, /*icon=*/nullptr,
-                          ui::mojom::DragEventSource::kTouch);
-  EXPECT_TRUE(seat_->get_drag_drop_operation_for_testing());
+  seat.StartDrag(&source, origin, /*icon=*/nullptr,
+                 ui::mojom::DragEventSource::kTouch);
+  EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
 
   // Initiate the gesture sequence.
   DispatchGesture(ui::ET_GESTURE_BEGIN, gfx::Point(10, 10));
@@ -1144,17 +1154,17 @@
   // As soon as the runloop gets triggered, emit a mouse release event.
   drag_drop_controller->SetLoopClosureForTesting(
       base::BindLambdaForTesting([&]() {
-        EXPECT_CALL(delegate, OnPointerEnter(_, _, _)).Times(0);
+        EXPECT_CALL(pointer_delegate, OnPointerEnter(_, _, _)).Times(0);
         // generator.ReleaseLeftButton();
         generator.set_current_screen_location(gfx::Point(10, 10));
         generator.PressMoveAndReleaseTouchBy(50, 50);
       }),
       base::DoNothing());
 
-  EXPECT_CALL(delegate, OnPointerLeave(_)).Times(0);
+  EXPECT_CALL(pointer_delegate, OnPointerLeave(_)).Times(0);
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_CALL(delegate, OnPointerDestroying(pointer.get()));
+  EXPECT_CALL(pointer_delegate, OnPointerDestroying(pointer.get()));
   pointer.reset();
 }
 
@@ -1168,20 +1178,22 @@
   SetHandledHandler handler;
   ash::Shell::Get()->AddPreTargetHandler(&handler);
 
-  testing::NiceMock<MockPointerDelegate> delegate;
-  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, seat_.get()));
+  Seat seat(std::make_unique<TestDataExchangeDelegate>());
+  testing::NiceMock<MockPointerDelegate> pointer_delegate;
+  std::unique_ptr<Pointer> pointer(new Pointer(&pointer_delegate, &seat));
 
   // Make origin into a real window so the touch can click it
   std::unique_ptr<ShellSurface> shell_surface =
       test::ShellSurfaceBuilder({10, 10}).BuildShellSurface();
 
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(testing::_))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(testing::_))
       .WillRepeatedly(testing::Return(true));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   // The SetHandlerHandler should have marked the event as processed. Therefore
   // the event should simply be ignored.
-  EXPECT_CALL(delegate, OnPointerButton(testing::_, testing::_, testing::_))
+  EXPECT_CALL(pointer_delegate,
+              OnPointerButton(testing::_, testing::_, testing::_))
       .Times(0);
 
   // This event should be ignored because it has already been handled.
@@ -1196,8 +1208,9 @@
 }
 
 TEST_P(PointerTest, IgnoresCursorHideEvents) {
-  testing::NiceMock<MockPointerDelegate> delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat(std::make_unique<TestDataExchangeDelegate>());
+  testing::NiceMock<MockPointerDelegate> pointer_delegate;
+  auto pointer = std::make_unique<Pointer>(&pointer_delegate, &seat);
 
   // Make origin into a real window so the touch can click it
   std::unique_ptr<ShellSurface> shell_surface =
@@ -1207,10 +1220,10 @@
   // it's not what we want so block here.
   // Note that, gmock puts priority to the later call, so the specific one
   // should come after the default one.
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(testing::_))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(testing::_))
       .WillRepeatedly(testing::Return(false));
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(
-                            shell_surface->surface_for_testing()))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(
+                                    shell_surface->surface_for_testing()))
       .WillRepeatedly(testing::Return(true));
 
   // Set up multi-display environment, and emulate the story that we hit
@@ -1226,62 +1239,50 @@
                           ->GetBoundsInScreen()
                           .CenterPoint();
   generator->MoveMouseTo(window_point);
-  ::testing::Mock::VerifyAndClearExpectations(&delegate);
+  ::testing::Mock::VerifyAndClearExpectations(&pointer_delegate);
 
   // Now dispatch a key event.
   // This key event internally generates MOUSE_EXITED pointer event with
   // CURSOR_HIDE|IS_SYNTHESIZED flags and dispatches to the tree.
   // Currently, wayland leave/enter events should be suppressed temporarily.
-  // See also crbug.com/1395073 what is the eventually expected state.
-  EXPECT_CALL(delegate, OnPointerLeave(testing::_)).Times(0);
-  EXPECT_CALL(delegate, OnPointerEnter(testing::_, testing::_, testing::_))
+  // See also crbug.com/1395073 what is the eventaully expected state.
+  EXPECT_CALL(pointer_delegate, OnPointerLeave(testing::_)).Times(0);
+  EXPECT_CALL(pointer_delegate,
+              OnPointerEnter(testing::_, testing::_, testing::_))
       .Times(0);
-  EXPECT_CALL(delegate, OnPointerFrame()).Times(0);
+  EXPECT_CALL(pointer_delegate, OnPointerFrame()).Times(0);
 
   // Re-set up CanAcceptPointerEventsForSurface, which was reset above.
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(testing::_))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(testing::_))
       .WillRepeatedly(testing::Return(false));
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(
-                            shell_surface->surface_for_testing()))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(
+                                    shell_surface->surface_for_testing()))
       .WillRepeatedly(testing::Return(true));
 
   // All set up of expectations is done, so dispatch the key event now.
   generator->PressKey(ui::VKEY_A, 0, 0);
 
-  ::testing::Mock::VerifyAndClearExpectations(&delegate);
+  ::testing::Mock::VerifyAndClearExpectations(&pointer_delegate);
 }
 
 namespace {
 
-class TestDataDevice : public DataDevice {
+class PointerDragDropObserver : public WMHelper::DragDropObserver {
  public:
-  using TestCallback = base::OnceCallback<void(ui::mojom::DragOperation&)>;
-
-  TestDataDevice(TestCallback closure, DataDeviceDelegate* delegate, Seat* seat)
-      : DataDevice(delegate, seat), closure_(std::move(closure)) {}
-  TestDataDevice(const TestDataDevice&) = delete;
-  const TestDataDevice operator=(const TestDataDevice&) = delete;
-
-  aura::client::DragDropDelegate::DropCallback GetDropCallback(
-      const ui::DropTargetEvent& event) override {
-    auto callback = DataDevice::GetDropCallback(event);
-    return base::BindOnce(&TestDataDevice::PerformDrop, base::Unretained(this),
-                          std::move(callback));
-  }
+  PointerDragDropObserver(DropCallback closure)
+      : closure_(std::move(closure)) {}
 
  private:
-  void PerformDrop(
-      aura::client::DragDropDelegate::DropCallback original_callback,
-      std::unique_ptr<ui::OSExchangeData> data,
-      ui::mojom::DragOperation& output_drag_op,
-      std::unique_ptr<ui::LayerTreeOwner> drag_image_layer_owner) {
-    std::move(closure_).Run(output_drag_op);
-    std::move(original_callback)
-        .Run(std::move(data), output_drag_op,
-             std::move(drag_image_layer_owner));
+  // WMHelper::DragDropObserver overrides:
+  void OnDragEntered(const ui::DropTargetEvent& event) override {}
+  aura::client::DragUpdateInfo OnDragUpdated(
+      const ui::DropTargetEvent& event) override {
+    return aura::client::DragUpdateInfo();
   }
+  void OnDragExited() override {}
+  DropCallback GetDropCallback() override { return std::move(closure_); }
 
-  TestCallback closure_;
+  DropCallback closure_;
 };
 
 }  // namespace
@@ -1290,8 +1291,9 @@
 // processed in case the target surface is destroyed during the drop action.
 TEST_P(PointerTest,
        DragDropAndPointerEnterLeaveEvents_NoEnterOnSurfaceDestroy) {
-  MockPointerDelegate delegate;
-  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, seat_.get()));
+  Seat seat(std::make_unique<TestDataExchangeDelegate>());
+  MockPointerDelegate pointer_delegate;
+  std::unique_ptr<Pointer> pointer(new Pointer(&pointer_delegate, &seat));
   TestDataSourceDelegate data_source_delegate;
   DataSource source(&data_source_delegate);
 
@@ -1301,15 +1303,17 @@
   auto closure = base::BindOnce([](std::unique_ptr<ShellSurface> shell_surface,
                                    ui::mojom::DragOperation& output_drag_op) {},
                                 std::move(shell_surface));
-  TestDataDevice data_device(std::move(closure), &data_device_delegate_,
-                             seat_.get());
+  PointerDragDropObserver drag_drop_observer(std::move(closure));
+
+  auto* wm_helper = WMHelper::GetInstance();
+  wm_helper->AddDragDropObserver(&drag_drop_observer);
 
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(origin_ptr))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(origin_ptr))
       .WillRepeatedly(testing::Return(true));
-  EXPECT_CALL(delegate, OnPointerFrame()).Times(AnyNumber());
-  EXPECT_CALL(delegate, OnPointerEnter(origin_ptr, gfx::PointF(), 0));
+  EXPECT_CALL(pointer_delegate, OnPointerFrame()).Times(AnyNumber());
+  EXPECT_CALL(pointer_delegate, OnPointerEnter(origin_ptr, gfx::PointF(), 0));
   generator.MoveMouseTo(origin_ptr->window()->GetBoundsInScreen().origin());
 
   auto* drag_drop_controller = static_cast<ash::DragDropController*>(
@@ -1317,9 +1321,9 @@
   ASSERT_TRUE(drag_drop_controller);
 
   generator.PressLeftButton();
-  data_device.StartDrag(&source, origin_ptr, /*icon=*/nullptr,
-                        ui::mojom::DragEventSource::kMouse);
-  EXPECT_TRUE(seat_->get_drag_drop_operation_for_testing());
+  seat.StartDrag(&source, origin_ptr, /*icon=*/nullptr,
+                 ui::mojom::DragEventSource::kMouse);
+  EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
 
   // As soon as the runloop gets triggered, emit a mouse release event.
   drag_drop_controller->SetLoopClosureForTesting(
@@ -1330,20 +1334,21 @@
       base::DoNothing());
 
   // OnPointerLeave() gets called when the drag starts;
-  EXPECT_CALL(delegate, OnPointerLeave(_)).Times(1);
-  EXPECT_CALL(delegate, OnPointerEnter(_, _, _)).Times(0);
+  EXPECT_CALL(pointer_delegate, OnPointerLeave(_)).Times(1);
+  EXPECT_CALL(pointer_delegate, OnPointerEnter(_, _, _)).Times(0);
 
   base::RunLoop().RunUntilIdle();
 
-  ::testing::Mock::VerifyAndClearExpectations(&delegate);
+  ::testing::Mock::VerifyAndClearExpectations(&pointer_delegate);
 
   EXPECT_TRUE(drag_drop_controller->IsDragDropCompleted());
   // There should be no mouse enter after dnd session either.
-  EXPECT_CALL(delegate, OnPointerEnter(_, _, _)).Times(0);
+  EXPECT_CALL(pointer_delegate, OnPointerEnter(_, _, _)).Times(0);
 
   generator.MoveMouseBy(1, 1);
+  wm_helper->RemoveDragDropObserver(&drag_drop_observer);
 
-  EXPECT_CALL(delegate, OnPointerDestroying(pointer.get()));
+  EXPECT_CALL(pointer_delegate, OnPointerDestroying(pointer.get()));
   pointer.reset();
 }
 
@@ -1352,8 +1357,9 @@
 // action.
 TEST_P(PointerTest,
        DragDropAndPointerEnterLeaveEvents_NoEnterOnParentSurfaceDestroy) {
-  MockPointerDelegate delegate;
-  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, seat_.get()));
+  Seat seat(std::make_unique<TestDataExchangeDelegate>());
+  MockPointerDelegate pointer_delegate;
+  std::unique_ptr<Pointer> pointer(new Pointer(&pointer_delegate, &seat));
   TestDataSourceDelegate data_source_delegate;
   DataSource source(&data_source_delegate);
 
@@ -1363,15 +1369,17 @@
   auto closure = base::BindOnce([](std::unique_ptr<ShellSurface> shell_surface,
                                    ui::mojom::DragOperation& output_drag_op) {},
                                 std::move(shell_surface));
-  TestDataDevice data_device(std::move(closure), &data_device_delegate_,
-                             seat_.get());
+  PointerDragDropObserver drag_drop_observer(std::move(closure));
+
+  auto* wm_helper = WMHelper::GetInstance();
+  wm_helper->AddDragDropObserver(&drag_drop_observer);
 
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(testing::_))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(testing::_))
       .WillRepeatedly(testing::Return(true));
-  EXPECT_CALL(delegate, OnPointerFrame()).Times(AnyNumber());
-  EXPECT_CALL(delegate, OnPointerEnter(surface, gfx::PointF(), 0));
+  EXPECT_CALL(pointer_delegate, OnPointerFrame()).Times(AnyNumber());
+  EXPECT_CALL(pointer_delegate, OnPointerEnter(surface, gfx::PointF(), 0));
   generator.MoveMouseTo(surface->window()->GetBoundsInScreen().origin());
 
   auto* drag_drop_controller = static_cast<ash::DragDropController*>(
@@ -1379,9 +1387,9 @@
   ASSERT_TRUE(drag_drop_controller);
 
   generator.PressLeftButton();
-  data_device.StartDrag(&source, surface, /*icon=*/nullptr,
-                        ui::mojom::DragEventSource::kMouse);
-  EXPECT_TRUE(seat_->get_drag_drop_operation_for_testing());
+  seat.StartDrag(&source, surface, /*icon=*/nullptr,
+                 ui::mojom::DragEventSource::kMouse);
+  EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
 
   // As soon as the runloop gets triggered, emit a mouse release event.
   drag_drop_controller->SetLoopClosureForTesting(
@@ -1394,15 +1402,17 @@
   // OnPointerLeave() gets called twice:
   // 1/ when the drag starts;
   // 2/ when the dragging window gets destroyed.
-  EXPECT_CALL(delegate, OnPointerLeave(_)).Times(1);
-  EXPECT_CALL(delegate, OnPointerEnter(_, _, _)).Times(0);
+  EXPECT_CALL(pointer_delegate, OnPointerLeave(_)).Times(1);
+  EXPECT_CALL(pointer_delegate, OnPointerEnter(_, _, _)).Times(0);
   base::RunLoop().RunUntilIdle();
 
-  ::testing::Mock::VerifyAndClearExpectations(&delegate);
+  ::testing::Mock::VerifyAndClearExpectations(&pointer_delegate);
 
   EXPECT_TRUE(drag_drop_controller->IsDragDropCompleted());
 
-  EXPECT_CALL(delegate, OnPointerDestroying(pointer.get()));
+  wm_helper->RemoveDragDropObserver(&drag_drop_observer);
+
+  EXPECT_CALL(pointer_delegate, OnPointerDestroying(pointer.get()));
   pointer.reset();
 }
 
@@ -1412,7 +1422,8 @@
 
   MockPointerDelegate delegate;
   MockRelativePointerDelegate relative_delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  auto pointer = std::make_unique<Pointer>(&delegate, &seat);
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
   pointer->RegisterRelativePointerDelegate(&relative_delegate);
 
@@ -1527,7 +1538,8 @@
 
   // Set up the pointer and move it to the origin.
   testing::NiceMock<MockPointerDelegate> delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  auto pointer = std::make_unique<Pointer>(&delegate, &seat);
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
       .WillRepeatedly(testing::Return(true));
@@ -1937,7 +1949,8 @@
 
   MockPointerDelegate delegate;
   MockPointerStylusDelegate stylus_delegate;
-  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, seat_.get()));
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   pointer->SetStylusDelegate(&stylus_delegate);
@@ -1967,7 +1980,8 @@
 
   MockPointerDelegate delegate;
   MockPointerStylusDelegate stylus_delegate;
-  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, seat_.get()));
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
 
   pointer->SetStylusDelegate(&stylus_delegate);
@@ -1999,12 +2013,13 @@
 }
 
 TEST_P(PointerTest, DontSendMouseEventDuringMove) {
-  testing::NiceMock<MockPointerDelegate> delegate;
-  auto pointer = std::make_unique<Pointer>(&delegate, seat_.get());
+  Seat seat;
+  testing::NiceMock<MockPointerDelegate> pointer_delegate;
+  auto pointer = std::make_unique<Pointer>(&pointer_delegate, &seat);
 
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(testing::_))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(testing::_))
       .WillRepeatedly(testing::Return(true));
-  EXPECT_CALL(delegate, OnPointerMotion).Times(0);
+  EXPECT_CALL(pointer_delegate, OnPointerMotion).Times(0);
 
   std::unique_ptr<ShellSurface> shell_surface =
       test::ShellSurfaceBuilder({64, 64})
@@ -2019,17 +2034,17 @@
   EXPECT_EQ(shell_surface->GetWidget()->GetWindowBoundsInScreen().origin(),
             gfx::Point(10, 10));
 
-  ::testing::Mock::VerifyAndClearExpectations(&delegate);
+  ::testing::Mock::VerifyAndClearExpectations(&pointer_delegate);
 
   // Make sure that we don't send mouse motion event while dragging a window.
-  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(testing::_))
+  EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(testing::_))
       .WillRepeatedly(testing::Return(true));
-  EXPECT_CALL(delegate, OnPointerMotion).Times(0);
+  EXPECT_CALL(pointer_delegate, OnPointerMotion).Times(0);
   generator->MoveMouseBy(1, 1);
   EXPECT_EQ(shell_surface->GetWidget()->GetWindowBoundsInScreen().origin(),
             gfx::Point(11, 11));
 
-  ::testing::Mock::VerifyAndClearExpectations(&delegate);
+  ::testing::Mock::VerifyAndClearExpectations(&pointer_delegate);
 }
 
 TEST_P(PointerTest, SetCursorWithSurfaceChange) {
@@ -2037,8 +2052,9 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
+  Seat seat;
   auto pointer = std::make_unique<Pointer>(
-      &delegate, seat_.get(), std::make_unique<PointerTestHostWindow>());
+      &delegate, &seat, std::make_unique<PointerTestHostWindow>());
   ui::test::EventGenerator* generator = AshTestBase::GetEventGenerator();
 
   EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface))
@@ -2101,7 +2117,8 @@
   auto* surface = shell_surface->surface_for_testing();
 
   MockPointerDelegate delegate;
-  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, seat_.get()));
+  Seat seat;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
   ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
   aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(
       shell_surface->GetWidget()->GetNativeWindow()->GetRootWindow());
diff --git a/components/exo/seat.h b/components/exo/seat.h
index ca8b231..b5a6ae1 100644
--- a/components/exo/seat.h
+++ b/components/exo/seat.h
@@ -205,7 +205,7 @@
   // Max value of SeatObserver's priority. Both side are inclusive.
   static constexpr int kMaxObserverPriority = 1;
 
-  // Map from priority to a list of SeatObserver pointers.
+  // Map from priority to a list of SeatOberver pointers.
   std::array<base::ObserverList<SeatObserver>::Unchecked,
              kMaxObserverPriority + 1>
       priority_observer_list_;
@@ -219,7 +219,6 @@
   // Data source being used as a clipboard content.
   std::unique_ptr<ScopedDataSource> selection_source_;
 
-  // TODO(oshima): Move this to DataDevice.
   base::WeakPtr<DragDropOperation> drag_drop_operation_;
 
   // True while Seat is updating clipboard data to selection source.
diff --git a/components/exo/seat_unittest.cc b/components/exo/seat_unittest.cc
index 2af7432..352af8b 100644
--- a/components/exo/seat_unittest.cc
+++ b/components/exo/seat_unittest.cc
@@ -12,15 +12,12 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
 #include "base/test/bind.h"
-#include "components/exo/data_device.h"
-#include "components/exo/data_device_delegate.h"
 #include "components/exo/data_source.h"
 #include "components/exo/data_source_delegate.h"
 #include "components/exo/seat_observer.h"
 #include "components/exo/surface.h"
 #include "components/exo/test/exo_test_base.h"
 #include "components/exo/test/exo_test_data_exchange_delegate.h"
-#include "components/exo/test/test_data_device_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/clipboard/clipboard.h"
@@ -745,9 +742,6 @@
 
 TEST_F(SeatTest, DragDropAbort) {
   TestSeat seat;
-  test::TestDataDeviceDelegate data_device_delegate;
-
-  DataDevice data_device(&data_device_delegate, &seat);
   TestDataSourceDelegate delegate;
   DataSource source(&delegate);
   Surface origin, icon;
@@ -755,8 +749,7 @@
   // Give origin a root window for DragDropOperation.
   GetContext()->AddChild(origin.window());
 
-  data_device.StartDrag(&source, &origin, &icon,
-                        ui::mojom::DragEventSource::kMouse);
+  seat.StartDrag(&source, &origin, &icon, ui::mojom::DragEventSource::kMouse);
   EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
   seat.AbortPendingDragOperation();
   EXPECT_FALSE(seat.get_drag_drop_operation_for_testing());
diff --git a/components/exo/sub_surface_unittest.cc b/components/exo/sub_surface_unittest.cc
index 5d1d3b7d..25001cd 100644
--- a/components/exo/sub_surface_unittest.cc
+++ b/components/exo/sub_surface_unittest.cc
@@ -142,7 +142,7 @@
   viz::CompositorFrame frame1;
   frame1.render_pass_list.push_back(viz::CompositorRenderPass::Create());
   parent->AppendSurfaceHierarchyContentsToFrame(
-      gfx::PointF{},
+      gfx::PointF{}, gfx::PointF{},
       /*needs_full_damage=*/false, frame_sink_holder->resource_manager(),
       /*device_scale_factor=*/absl::nullopt, &frame1);
 
@@ -156,7 +156,7 @@
   viz::CompositorFrame frame2;
   frame2.render_pass_list.push_back(viz::CompositorRenderPass::Create());
   parent->AppendSurfaceHierarchyContentsToFrame(
-      gfx::PointF{},
+      gfx::PointF{}, gfx::PointF{},
       /*needs_full_damage=*/false, frame_sink_holder->resource_manager(),
       /*device_scale_factor=*/absl::nullopt, &frame2);
 
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index 1f883be9..af3f258 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -326,8 +326,8 @@
   window_->Init(ui::LAYER_NOT_DRAWN);
   window_->SetEventTargeter(std::make_unique<CustomWindowTargeter>());
   window_->set_owned_by_parent(false);
+  WMHelper::GetInstance()->SetDragDropDelegate(window_.get());
 }
-
 Surface::~Surface() {
   for (SurfaceObserver& observer : observers_)
     observer.OnSurfaceDestroying(this);
@@ -1222,7 +1222,8 @@
 }
 
 void Surface::AppendSurfaceHierarchyContentsToFrame(
-    const gfx::PointF& origin,
+    const gfx::PointF& parent_to_root_px,
+    const gfx::PointF& to_parent_dp,
     bool needs_full_damage,
     FrameSinkResourceManager* resource_manager,
     absl::optional<float> device_scale_factor,
@@ -1233,8 +1234,12 @@
     auto* sub_surface = sub_surface_entry.first;
     // Synchronsouly commit all pending state of the sub-surface and its
     // decendents.
+    gfx::PointF to_root_px =
+        parent_to_root_px +
+        gfx::ScalePoint(to_parent_dp, device_scale_factor.value_or(1.f))
+            .OffsetFromOrigin();
     sub_surface->AppendSurfaceHierarchyContentsToFrame(
-        origin + sub_surface_entry.second.OffsetFromOrigin(), needs_full_damage,
+        to_root_px, sub_surface_entry.second, needs_full_damage,
         resource_manager, device_scale_factor, frame);
   }
 
@@ -1247,7 +1252,8 @@
         std::move(state_.per_commit_explicit_release_callback_));
   }
 
-  AppendContentsToFrame(origin, needs_full_damage, device_scale_factor, frame);
+  AppendContentsToFrame(parent_to_root_px, to_parent_dp, needs_full_damage,
+                        device_scale_factor, frame);
 }
 
 bool Surface::IsSynchronized() const {
@@ -1519,38 +1525,44 @@
   return quad_state;
 }
 
-void Surface::AppendContentsToFrame(const gfx::PointF& origin,
+void Surface::AppendContentsToFrame(const gfx::PointF& parent_to_root_px,
+                                    const gfx::PointF& to_parent_dp,
                                     bool needs_full_damage,
                                     absl::optional<float> device_scale_factor,
                                     viz::CompositorFrame* frame) {
   const std::unique_ptr<viz::CompositorRenderPass>& render_pass =
       frame->render_pass_list.back();
-  gfx::RectF output_rect(origin, content_size_);
+  gfx::PointF parent_to_root_dp = gfx::ScalePoint(
+      parent_to_root_px, 1.f / device_scale_factor.value_or(1.f));
+  gfx::PointF to_root_dp = parent_to_root_dp + to_parent_dp.OffsetFromOrigin();
+  gfx::RectF output_rect(to_root_dp, content_size_);
   gfx::Rect quad_rect(0, 0, 1, 1);
 
-  // Surface bounds are in DIPs, but |damage_rect| and |output_rect| are in
+  // Surface bounds are in DIPs, but |damage_rect| should be specified in
   // pixels, so we need to scale by the |device_scale_factor|.
-  gfx::RectF damage_rect = needs_full_damage
-                               ? gfx::RectF(content_size_)
-                               : gfx::RectF(state_.damage.bounds());
-  if (!damage_rect.IsEmpty()) {
+  gfx::RectF damage_rect_px;
+  gfx::RectF damage_rect_dp = needs_full_damage
+                                  ? gfx::RectF(content_size_)
+                                  : gfx::RectF(state_.damage.bounds());
+  if (!damage_rect_dp.IsEmpty()) {
     // Outset damage by 1 DIP to as damage is in surface coordinate space and
     // client might not be aware of |device_scale_factor| and the
     // scaling/filtering it requires.
-    damage_rect.Inset(-1);
-    damage_rect += origin.OffsetFromOrigin();
-    damage_rect.Intersect(output_rect);
+    damage_rect_dp.Inset(-1);
+    damage_rect_dp += to_root_dp.OffsetFromOrigin();
+    damage_rect_dp.Intersect(output_rect);
 
+    damage_rect_px = damage_rect_dp;
     if (device_scale_factor.has_value()) {
       if (device_scale_factor.value() <= 1) {
-        damage_rect =
-            gfx::ConvertRectToPixels(damage_rect, device_scale_factor.value());
+        damage_rect_px = gfx::ConvertRectToPixels(damage_rect_px,
+                                                  device_scale_factor.value());
       } else {
         // The damage will eventually be rescaled by 1/device_scale_factor.
         // Since that scale factor is <1, taking the enclosed rect here means
         // that that rescaled RectF is <1px smaller than |damage_rect| in each
         // dimension, which makes the enclosing rect equal to |damage_rect|.
-        damage_rect.Scale(device_scale_factor.value());
+        damage_rect_px.Scale(device_scale_factor.value());
       }
     }
   }
@@ -1562,9 +1574,12 @@
     // we skip translating into the root surface coordinates to keep the old
     // behavior.
     // TODO(crbug.com/1457446): Remove this.
-    auto clip_rect_offset = state_.clip_rect_is_parent_coordinates
-                                ? gfx::Vector2d()
-                                : origin.OffsetFromOrigin();
+    auto clip_rect_offset =
+        state_.clip_rect_is_parent_coordinates
+            ? parent_to_root_px.OffsetFromOrigin()
+            : gfx::ScalePoint(to_root_dp, device_scale_factor.value_or(1.f))
+                  .OffsetFromOrigin();
+
     quad_clip_rect = gfx::ToEnclosedRect(*state_.clip_rect + clip_rect_offset);
   }
 
@@ -1609,8 +1624,9 @@
     // old behavior.
     // TODO(crbug.com/1470955): Remove this.
     auto rounded_corners_rect_offset =
-        state_.rounded_corners_is_root_coordinates ? gfx::Vector2d()
-                                                   : origin.OffsetFromOrigin();
+        state_.rounded_corners_is_root_coordinates
+            ? parent_to_root_dp.OffsetFromOrigin()
+            : to_root_dp.OffsetFromOrigin();
 
     // Set the mask.
     msk = gfx::MaskFilterInfo(state_.rounded_corners_bounds +
@@ -1624,16 +1640,19 @@
 
   // Compute the total transformation from post-transform buffer coordinates to
   // target coordinates.
-  // Scale and offset the normalized space to fit the content size rectangle.
+  // Scale to size then translate to position of subsurface in parent's space.
   gfx::Transform viewport_to_target_transform(
       gfx::AxisTransform2d::FromScaleAndTranslation(
-          scale, origin.OffsetFromOrigin() + translate));
+          scale, to_parent_dp.OffsetFromOrigin() + translate));
+  // Apply delegated transform matrix
   viewport_to_target_transform.PostConcat(state_.surface_transform);
-
   if (device_scale_factor.has_value()) {
     // Convert from DPs to pixels.
     viewport_to_target_transform.PostScale(device_scale_factor.value());
   }
+  // Translate to root in pixels.
+  viewport_to_target_transform.PostTranslate(
+      parent_to_root_px.OffsetFromOrigin());
 
   gfx::Transform quad_to_target_transform(buffer_transform_);
   quad_to_target_transform.PostConcat(viewport_to_target_transform);
@@ -1762,11 +1781,11 @@
         }
 #endif  // BUILDFLAG(USE_ARC_PROTECTED_MEDIA)
 
-        if (!damage_rect.IsEmpty()) {
-          texture_quad->damage_rect = gfx::ToEnclosedRect(damage_rect);
+        if (!damage_rect_px.IsEmpty()) {
+          texture_quad->damage_rect = gfx::ToEnclosedRect(damage_rect_px);
           render_pass->has_per_quad_damage = true;
           // Clear handled damage so it will not be added to the |render_pass|.
-          damage_rect = gfx::RectF();
+          damage_rect_px = gfx::RectF();
         }
       } else {
         viz::TileDrawQuad* tile_quad =
@@ -1797,7 +1816,7 @@
                        false /* force_anti_aliasing_off */);
   }
 
-  render_pass->damage_rect.Union(gfx::ToEnclosedRect(damage_rect));
+  render_pass->damage_rect.Union(gfx::ToEnclosedRect(damage_rect_px));
 }
 
 void Surface::UpdateContentSize() {
diff --git a/components/exo/surface.h b/components/exo/surface.h
index 778b2bb..df4e86a 100644
--- a/components/exo/surface.h
+++ b/components/exo/surface.h
@@ -331,7 +331,8 @@
 
   // This will append contents for surface and its descendants to frame.
   void AppendSurfaceHierarchyContentsToFrame(
-      const gfx::PointF& origin,
+      const gfx::PointF& parent_to_root_px,
+      const gfx::PointF& to_parent_dp,
       bool needs_full_damage,
       FrameSinkResourceManager* resource_manager,
       absl::optional<float> device_scale_factor,
@@ -646,7 +647,8 @@
 
   // Puts the current surface into a draw quad, and appends the draw quads into
   // the |frame|.
-  void AppendContentsToFrame(const gfx::PointF& origin,
+  void AppendContentsToFrame(const gfx::PointF& parent_to_root_px,
+                             const gfx::PointF& to_parent_dp,
                              bool needs_full_damage,
                              absl::optional<float> device_scale_factor,
                              viz::CompositorFrame* frame);
diff --git a/components/exo/surface_tree_host.cc b/components/exo/surface_tree_host.cc
index 8e0b291..bc4d849 100644
--- a/components/exo/surface_tree_host.cc
+++ b/components/exo/surface_tree_host.cc
@@ -337,7 +337,7 @@
       std::move(presentation_callbacks);
 
   root_surface_->AppendSurfaceHierarchyContentsToFrame(
-      gfx::PointF(root_surface_origin_pixel_),
+      gfx::PointF(root_surface_origin_pixel_), /*to_parent_dp=*/gfx::PointF(),
       layer_tree_frame_sink_holder_->NeedsFullDamageForNextFrame(),
       layer_tree_frame_sink_holder_->resource_manager(),
       client_submits_surfaces_in_pixel_coordinates()
diff --git a/components/exo/test/test_data_device_delegate.cc b/components/exo/test/test_data_device_delegate.cc
deleted file mode 100644
index 538bbf2..0000000
--- a/components/exo/test/test_data_device_delegate.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/exo/test/test_data_device_delegate.h"
-
-#include "components/exo/data_offer_delegate.h"
-
-namespace exo::test {
-namespace {
-
-class TestDataOfferDelegate : public DataOfferDelegate {
- public:
-  TestDataOfferDelegate() = default;
-  TestDataOfferDelegate(const TestDataOfferDelegate&) = delete;
-  const TestDataOfferDelegate operator=(const TestDataOfferDelegate&) = delete;
-  ~TestDataOfferDelegate() override = default;
-
-  // Overridden from DataOfferDelegate:
-  void OnDataOfferDestroying(DataOffer* offer) override { delete this; }
-  void OnOffer(const std::string& mime_type) override {}
-  void OnSourceActions(
-      const base::flat_set<DndAction>& source_actions) override {}
-  void OnAction(DndAction action) override {}
-};
-
-}  // namespace
-
-TestDataDeviceDelegate::TestDataDeviceDelegate() = default;
-TestDataDeviceDelegate::~TestDataDeviceDelegate() = default;
-
-size_t TestDataDeviceDelegate::PopEvents(std::vector<DataEvent>* out) {
-  out->swap(events_);
-  events_.clear();
-  return out->size();
-}
-
-void TestDataDeviceDelegate::DeleteDataOffer(bool finished) {
-  if (finished) {
-    data_offer_->Finish();
-  }
-  data_offer_.reset();
-}
-
-void TestDataDeviceDelegate::OnDataDeviceDestroying(DataDevice* data_device) {
-  events_.push_back(DataEvent::kDestroy);
-}
-
-DataOffer* TestDataDeviceDelegate::OnDataOffer() {
-  events_.push_back(DataEvent::kOffer);
-  data_offer_ = std::make_unique<DataOffer>(new TestDataOfferDelegate);
-  return data_offer_.get();
-}
-
-void TestDataDeviceDelegate::OnEnter(Surface* surface,
-                                     const gfx::PointF& location,
-                                     const DataOffer& data_offer) {
-  events_.push_back(DataEvent::kEnter);
-  entered_surface_ = surface;
-}
-
-void TestDataDeviceDelegate::OnLeave() {
-  events_.push_back(DataEvent::kLeave);
-}
-
-void TestDataDeviceDelegate::OnMotion(base::TimeTicks time_stamp,
-                                      const gfx::PointF& location) {
-  events_.push_back(DataEvent::kMotion);
-}
-
-void TestDataDeviceDelegate::OnDrop() {
-  events_.push_back(DataEvent::kDrop);
-}
-
-void TestDataDeviceDelegate::OnSelection(const DataOffer& data_offer) {
-  events_.push_back(DataEvent::kSelection);
-}
-
-bool TestDataDeviceDelegate::CanAcceptDataEventsForSurface(
-    Surface* surface) const {
-  return can_accept_data_events_for_surface_;
-}
-
-}  // namespace exo::test
diff --git a/components/exo/test/test_data_device_delegate.h b/components/exo/test/test_data_device_delegate.h
deleted file mode 100644
index 6c5a4bdb..0000000
--- a/components/exo/test/test_data_device_delegate.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_EXO_TEST_TEST_DATA_DEVICE_DELEGATE_H_
-#define COMPONENTS_EXO_TEST_TEST_DATA_DEVICE_DELEGATE_H_
-
-#include <vector>
-
-#include "base/memory/raw_ptr.h"
-#include "components/exo/data_device_delegate.h"
-
-namespace exo::test {
-
-enum class DataEvent {
-  kOffer,
-  kEnter,
-  kLeave,
-  kMotion,
-  kDrop,
-  kDestroy,
-  kSelection
-};
-
-class TestDataDeviceDelegate : public DataDeviceDelegate {
- public:
-  TestDataDeviceDelegate();
-
-  TestDataDeviceDelegate(const TestDataDeviceDelegate&) = delete;
-  TestDataDeviceDelegate& operator=(const TestDataDeviceDelegate&) = delete;
-
-  ~TestDataDeviceDelegate() override;
-
-  size_t PopEvents(std::vector<DataEvent>* out);
-  Surface* entered_surface() const { return entered_surface_; }
-  void DeleteDataOffer(bool finished);
-  void set_can_accept_data_events_for_surface(bool value) {
-    can_accept_data_events_for_surface_ = value;
-  }
-
-  // Overridden from DataDeviceDelegate:
-  void OnDataDeviceDestroying(DataDevice* data_device) override;
-  DataOffer* OnDataOffer() override;
-  void OnEnter(Surface* surface,
-               const gfx::PointF& location,
-               const DataOffer& data_offer) override;
-  void OnLeave() override;
-  void OnMotion(base::TimeTicks time_stamp,
-                const gfx::PointF& location) override;
-  void OnDrop() override;
-  void OnSelection(const DataOffer& data_offer) override;
-  bool CanAcceptDataEventsForSurface(Surface* surface) const override;
-
- private:
-  std::vector<DataEvent> events_;
-  std::unique_ptr<DataOffer> data_offer_;
-  raw_ptr<Surface, DanglingUntriaged | ExperimentalAsh> entered_surface_ =
-      nullptr;
-  bool can_accept_data_events_for_surface_ = true;
-};
-
-}  // namespace exo::test
-
-#endif  // COMPONENTS_EXO_TEST_TEST_DATA_DEVICE_DELEGATE_H_
diff --git a/components/exo/touch_unittest.cc b/components/exo/touch_unittest.cc
index 89ec396..b2f7bcd 100644
--- a/components/exo/touch_unittest.cc
+++ b/components/exo/touch_unittest.cc
@@ -18,7 +18,6 @@
 #include "components/exo/test/exo_test_data_exchange_delegate.h"
 #include "components/exo/test/exo_test_helper.h"
 #include "components/exo/test/shell_surface_builder.h"
-#include "components/exo/test/test_data_device_delegate.h"
 #include "components/exo/touch_delegate.h"
 #include "components/exo/touch_stylus_delegate.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -532,8 +531,7 @@
 
 TEST_F(TouchTest, DragDropAbort) {
   Seat seat(std::make_unique<TestDataExchangeDelegate>());
-  test::TestDataDeviceDelegate data_device_delegate;
-  DataDevice data_device(&data_device_delegate, &seat);
+
   MockTouchDelegate touch_delegate;
   std::unique_ptr<Touch> touch(new Touch(&touch_delegate, &seat));
   TestDataSourceDelegate data_source_delegate;
@@ -553,8 +551,7 @@
   EXPECT_CALL(touch_delegate, OnTouchFrame()).Times(2);
   generator.MoveTouch(origin.window()->GetBoundsInScreen().origin());
 
-  data_device.StartDrag(&source, &origin, &icon,
-                        ui::mojom::DragEventSource::kMouse);
+  seat.StartDrag(&source, &origin, &icon, ui::mojom::DragEventSource::kMouse);
   EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
 
   EXPECT_CALL(touch_delegate, OnTouchDown).Times(1);
diff --git a/components/exo/wm_helper.cc b/components/exo/wm_helper.cc
index c2c7674d..dfd3a81 100644
--- a/components/exo/wm_helper.cc
+++ b/components/exo/wm_helper.cc
@@ -205,6 +205,22 @@
   aura::client::GetFocusClient(GetPrimaryRoot())->RemoveObserver(observer);
 }
 
+void WMHelper::AddDragDropObserver(DragDropObserver* observer) {
+  drag_drop_observers_.AddObserver(observer);
+}
+
+void WMHelper::RemoveDragDropObserver(DragDropObserver* observer) {
+  drag_drop_observers_.RemoveObserver(observer);
+}
+
+void WMHelper::SetDragDropDelegate(aura::Window* window) {
+  aura::client::SetDragDropDelegate(window, this);
+}
+
+void WMHelper::ResetDragDropDelegate(aura::Window* window) {
+  aura::client::SetDragDropDelegate(window, nullptr);
+}
+
 void WMHelper::AddPowerObserver(WMHelper::PowerObserver* observer) {
   power_observers_.AddObserver(observer);
 }
@@ -351,6 +367,50 @@
   return wm::CaptureController::Get();
 }
 
+void WMHelper::OnDragEntered(const ui::DropTargetEvent& event) {
+  for (DragDropObserver& observer : drag_drop_observers_) {
+    observer.OnDragEntered(event);
+  }
+}
+
+aura::client::DragUpdateInfo WMHelper::OnDragUpdated(
+    const ui::DropTargetEvent& event) {
+  aura::client::DragUpdateInfo drag_info(
+      ui::DragDropTypes::DRAG_NONE,
+      ui::DataTransferEndpoint(ui::EndpointType::kUnknownVm));
+
+  for (DragDropObserver& observer : drag_drop_observers_) {
+    auto observer_drag_info = observer.OnDragUpdated(event);
+    drag_info.drag_operation =
+        drag_info.drag_operation | observer_drag_info.drag_operation;
+    if (observer_drag_info.data_endpoint.type() !=
+        drag_info.data_endpoint.type()) {
+      drag_info.data_endpoint = observer_drag_info.data_endpoint;
+    }
+  }
+  return drag_info;
+}
+
+void WMHelper::OnDragExited() {
+  for (DragDropObserver& observer : drag_drop_observers_) {
+    observer.OnDragExited();
+  }
+}
+
+aura::client::DragDropDelegate::DropCallback WMHelper::GetDropCallback(
+    const ui::DropTargetEvent& event) {
+  std::vector<WMHelper::DragDropObserver::DropCallback> drop_callbacks;
+  for (DragDropObserver& observer : drag_drop_observers_) {
+    WMHelper::DragDropObserver::DropCallback drop_cb =
+        observer.GetDropCallback();
+    if (!drop_cb.is_null()) {
+      drop_callbacks.push_back(std::move(drop_cb));
+    }
+  }
+  return base::BindOnce(&WMHelper::PerformDrop, weak_ptr_factory_.GetWeakPtr(),
+                        std::move(drop_callbacks));
+}
+
 void WMHelper::SuspendDone(base::TimeDelta sleep_duration) {
   for (PowerObserver& observer : power_observers_) {
     observer.SuspendDone();
@@ -382,6 +442,20 @@
   exo_window_observers_.RemoveObserver(observer);
 }
 
+void WMHelper::PerformDrop(
+    std::vector<WMHelper::DragDropObserver::DropCallback> drop_callbacks,
+    std::unique_ptr<ui::OSExchangeData> data,
+    ui::mojom::DragOperation& output_drag_op,
+    std::unique_ptr<ui::LayerTreeOwner> drag_image_layer_owner) {
+  for (auto& drop_cb : drop_callbacks) {
+    auto operation = ui::mojom::DragOperation::kNone;
+    std::move(drop_cb).Run(operation);
+    if (operation != ui::mojom::DragOperation::kNone) {
+      output_drag_op = operation;
+    }
+  }
+}
+
 float GetDefaultDeviceScaleFactor() {
   if (!display::HasInternalDisplay()) {
     return 1.0;
diff --git a/components/exo/wm_helper.h b/components/exo/wm_helper.h
index 0b2b53a9..2deb688 100644
--- a/components/exo/wm_helper.h
+++ b/components/exo/wm_helper.h
@@ -15,7 +15,9 @@
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "components/exo/vsync_timing_manager.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
+#include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/base/cursor/cursor.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
 
 namespace aura {
 class Window;
@@ -43,6 +45,7 @@
 
 namespace ui {
 class EventHandler;
+class DropTargetEvent;
 class PropertyHandler;
 }  // namespace ui
 
@@ -55,8 +58,25 @@
 
 // Helper interface for accessing WindowManager related features.
 class WMHelper : public chromeos::PowerManagerClient::Observer,
+                 public aura::client::DragDropDelegate,
                  public VSyncTimingManager::Delegate {
  public:
+
+  class DragDropObserver {
+   public:
+    using DropCallback =
+        base::OnceCallback<void(ui::mojom::DragOperation& output_drag_op)>;
+
+    virtual void OnDragEntered(const ui::DropTargetEvent& event) = 0;
+    virtual aura::client::DragUpdateInfo OnDragUpdated(
+        const ui::DropTargetEvent& event) = 0;
+    virtual void OnDragExited() = 0;
+    virtual DropCallback GetDropCallback() = 0;
+
+   protected:
+    virtual ~DragDropObserver() {}
+  };
+
   // Used to notify objects when WMHelper is being destroyed. This allows
   // objects that wait for various external depenencies to cleanup as part of
   // the shutdown process.
@@ -155,6 +175,10 @@
   void RemoveTooltipObserver(wm::TooltipObserver* observer);
   void AddFocusObserver(aura::client::FocusChangeObserver* observer);
   void RemoveFocusObserver(aura::client::FocusChangeObserver* observer);
+  void AddDragDropObserver(DragDropObserver* observer);
+  void RemoveDragDropObserver(DragDropObserver* observer);
+  void SetDragDropDelegate(aura::Window*);
+  void ResetDragDropDelegate(aura::Window*);
   void AddPowerObserver(WMHelper::PowerObserver* observer);
   void RemovePowerObserver(WMHelper::PowerObserver* observer);
   VSyncTimingManager& GetVSyncTimingManager();
@@ -190,6 +214,14 @@
   LifetimeManager* GetLifetimeManager();
   aura::client::CaptureClient* GetCaptureClient();
 
+  // Overridden from aura::client::DragDropDelegate:
+  void OnDragEntered(const ui::DropTargetEvent& event) override;
+  aura::client::DragUpdateInfo OnDragUpdated(
+      const ui::DropTargetEvent& event) override;
+  void OnDragExited() override;
+  aura::client::DragDropDelegate::DropCallback GetDropCallback(
+      const ui::DropTargetEvent& event) override;
+
   // Overridden from chromeos::PowerManagerClient::Observer:
   void SuspendDone(base::TimeDelta sleep_duration) override;
   void ScreenBrightnessChanged(
@@ -203,10 +235,17 @@
       override;
 
  private:
+  void PerformDrop(
+      std::vector<WMHelper::DragDropObserver::DropCallback> drop_callbacks,
+      std::unique_ptr<ui::OSExchangeData> data,
+      ui::mojom::DragOperation& output_drag_op,
+      std::unique_ptr<ui::LayerTreeOwner> drag_image_layer_owner);
+
   base::ObserverList<ExoWindowObserver> exo_window_observers_;
 
   std::vector<std::unique_ptr<AppPropertyResolver>> resolver_list_;
 
+  base::ObserverList<DragDropObserver>::Unchecked drag_drop_observers_;
   base::ObserverList<PowerObserver> power_observers_;
   LifetimeManager lifetime_manager_;
   VSyncTimingManager vsync_timing_manager_;
diff --git a/components/exo/wm_helper_unittest.cc b/components/exo/wm_helper_unittest.cc
index df2d4bf3..26ca471 100644
--- a/components/exo/wm_helper_unittest.cc
+++ b/components/exo/wm_helper_unittest.cc
@@ -29,8 +29,36 @@
 #include "ui/gfx/geometry/point_f.h"
 
 namespace exo {
+namespace {
 
 using ::ui::mojom::DragOperation;
+
+class MockDragDropObserver : public WMHelper::DragDropObserver {
+ public:
+  MockDragDropObserver(DragOperation drop_result) : drop_result_(drop_result) {}
+  ~MockDragDropObserver() override = default;
+
+  // WMHelper::DragDropObserver:
+  void OnDragEntered(const ui::DropTargetEvent& event) override {}
+  aura::client::DragUpdateInfo OnDragUpdated(
+      const ui::DropTargetEvent& event) override {
+    return aura::client::DragUpdateInfo();
+  }
+  void OnDragExited() override {}
+  WMHelper::DragDropObserver::DropCallback GetDropCallback() override {
+    return base::BindOnce(
+        [](DragOperation drop_result, DragOperation& output_drag_op) {
+          output_drag_op = drop_result;
+        },
+        drop_result_);
+  }
+
+ private:
+  DragOperation drop_result_;
+};
+
+}  // namespace
+
 using WMHelperTest = test::ExoTestBase;
 
 TEST_F(WMHelperTest, FrameThrottling) {
@@ -76,6 +104,31 @@
   wm_helper_chromeos->RemoveFrameThrottlingObserver();
 }
 
+TEST_F(WMHelperTest, MultipleDragDropObservers) {
+  WMHelper* wm_helper_chromeos = static_cast<WMHelper*>(wm_helper());
+  MockDragDropObserver observer_no_drop(DragOperation::kNone);
+  MockDragDropObserver observer_copy_drop(DragOperation::kCopy);
+
+  wm_helper_chromeos->AddDragDropObserver(&observer_no_drop);
+
+  ui::DropTargetEvent target_event(ui::OSExchangeData(), gfx::PointF(),
+                                   gfx::PointF(), ui::DragDropTypes::DRAG_NONE);
+  auto drop_cb = wm_helper_chromeos->GetDropCallback(target_event);
+  DragOperation output_drop_op = DragOperation::kNone;
+  std::move(drop_cb).Run(std::make_unique<ui::OSExchangeData>(), output_drop_op,
+                         /*drag_image_layer_owner=*/nullptr);
+  EXPECT_EQ(output_drop_op, DragOperation::kNone);
+
+  wm_helper_chromeos->AddDragDropObserver(&observer_copy_drop);
+  drop_cb = wm_helper_chromeos->GetDropCallback(target_event);
+  std::move(drop_cb).Run(std::make_unique<ui::OSExchangeData>(), output_drop_op,
+                         /*drag_image_layer_owner=*/nullptr);
+  EXPECT_NE(output_drop_op, DragOperation::kNone);
+
+  wm_helper_chromeos->RemoveDragDropObserver(&observer_no_drop);
+  wm_helper_chromeos->RemoveDragDropObserver(&observer_copy_drop);
+}
+
 TEST_F(WMHelperTest, DockedModeShouldUseInternalAsDefault) {
   UpdateDisplay("1920x1080*2, 600x400");
   display::test::DisplayManagerTestApi(display_manager())
diff --git a/components/infobars/android/res/layout/infobar_control_toggle.xml b/components/infobars/android/res/layout/infobar_control_toggle.xml
index c615ca9..209d2a1 100644
--- a/components/infobars/android/res/layout/infobar_control_toggle.xml
+++ b/components/infobars/android/res/layout/infobar_control_toggle.xml
@@ -30,7 +30,7 @@
         android:gravity="center_vertical"
         android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
 
-    <com.google.android.material.switchmaterial.SwitchMaterial
+    <com.google.android.material.materialswitch.MaterialSwitch
         android:id="@+id/control_toggle_switch"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
diff --git a/components/media_control/renderer/BUILD.gn b/components/media_control/renderer/BUILD.gn
index 885b515..f9ba641 100644
--- a/components/media_control/renderer/BUILD.gn
+++ b/components/media_control/renderer/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 
 declare_args() {
   enable_media_control_logging_override = is_castos || is_cast_android
diff --git a/components/metrics/generate_expired_histograms_array.gni b/components/metrics/generate_expired_histograms_array.gni
index dea89aef7..8cc8298 100644
--- a/components/metrics/generate_expired_histograms_array.gni
+++ b/components/metrics/generate_expired_histograms_array.gni
@@ -122,6 +122,7 @@
       "//tools/metrics/histograms/metadata/memory/histograms.xml",
       "//tools/metrics/histograms/metadata/mobile/histograms.xml",
       "//tools/metrics/histograms/metadata/na_cl/histograms.xml",
+      "//tools/metrics/histograms/metadata/navigation/enums.xml",
       "//tools/metrics/histograms/metadata/navigation/histograms.xml",
       "//tools/metrics/histograms/metadata/nearby/histograms.xml",
       "//tools/metrics/histograms/metadata/net/histograms.xml",
diff --git a/components/nacl/features.gni b/components/nacl/features.gni
index a731e4f..fecb7951 100644
--- a/components/nacl/features.gni
+++ b/components/nacl/features.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/gclient_args.gni")
 
 # The NaCl sandbox and toolchain currently only support x86-32, x86-64
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc
index 8859a83..0949a61f 100644
--- a/components/omnibox/browser/autocomplete_controller.cc
+++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -1109,6 +1109,7 @@
   UpdateAssistedQueryStats(&internal_result_);
   UpdateTailSuggestPrefix(&internal_result_);
   MaybeRemoveCompanyEntityImages(&internal_result_);
+  MaybeCleanDefaultSuggestionForKeywordMode(input_.text(), &internal_result_);
 
   if (search_provider_)
     search_provider_->RegisterDisplayedAnswers(internal_result_);
@@ -1234,7 +1235,10 @@
 
     // Only add the keyword if the match does not have a duplicate keyword with
     // a more relevant match.
-    if (!keyword.empty() && !keywords.count(keyword)) {
+    if (!keyword.empty() &&
+        (!keywords.count(keyword) ||
+         (OmniboxFieldTrial::IsKeywordModeRefreshEnabled() &&
+          match.type == AutocompleteMatchType::STARTER_PACK))) {
       keywords.insert(keyword);
       match.associated_keyword = std::make_unique<AutocompleteMatch>(
           keyword_provider_->CreateVerbatimMatch(match.fill_into_edit, keyword,
@@ -1897,3 +1901,20 @@
     }
   }
 }
+
+void AutocompleteController::MaybeCleanDefaultSuggestionForKeywordMode(
+    const std::u16string& input,
+    AutocompleteResult* result) {
+  // Intentionally avoid actions and remove button on first suggestion
+  // which may interfere with keyword mode refresh.
+  if (OmniboxFieldTrial::IsKeywordModeRefreshEnabled() &&
+      input.starts_with(u'@') && result->size() > 1 &&
+      result->match_at(1)->type == AutocompleteMatchType::STARTER_PACK) {
+    result->match_at(0)->actions.clear();
+    result->match_at(0)->deletable = false;
+    for (AutocompleteMatch& duplicate :
+         result->match_at(0)->duplicate_matches) {
+      duplicate.deletable = false;
+    }
+  }
+}
diff --git a/components/omnibox/browser/autocomplete_controller.h b/components/omnibox/browser/autocomplete_controller.h
index 958d3c1d..6fff608 100644
--- a/components/omnibox/browser/autocomplete_controller.h
+++ b/components/omnibox/browser/autocomplete_controller.h
@@ -433,6 +433,11 @@
   // feature is enabled.
   void MaybeRemoveCompanyEntityImages(AutocompleteResult* result);
 
+  // May remove actions from default suggestion to avoid interference with
+  // keyword mode refresh interaction.
+  void MaybeCleanDefaultSuggestionForKeywordMode(const std::u16string& input,
+                                                 AutocompleteResult* result);
+
   base::ObserverList<Observer> observers_;
 
   // The client passed to the providers.
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc
index c7898661..a7065d34 100644
--- a/components/omnibox/browser/omnibox_edit_model.cc
+++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -895,8 +895,7 @@
     OmniboxEventProto::KeywordModeEntryMethod entry_method) {
   TRACE_EVENT0("omnibox", "OmniboxEditModel::AcceptKeyword");
 
-  DCHECK(is_keyword_hint_ && !keyword_.empty())
-      << "is_keyword_hint_: " << is_keyword_hint_ << ", keyword_: " << keyword_;
+  DCHECK(!keyword_.empty()) << keyword_;
 
   controller_->autocomplete_controller()->Stop(false);
 
@@ -2113,12 +2112,20 @@
       controller_->result(), GetPrefService(),
       controller_->client()->GetTemplateURLService(), direction, step);
   if (OmniboxFieldTrial::IsKeywordModeRefreshEnabled()) {
-    ClearKeyword();
-    SetPopupSelection(new_selection);
-    if (new_selection.state == OmniboxPopupSelection::LineState::KEYWORD_MODE) {
-      AcceptKeyword(old_selection.line == new_selection.line
-                        ? metrics::OmniboxEventProto::TAB
-                        : metrics::OmniboxEventProto::SELECT_SUGGESTION);
+    if (old_selection.IsChangeToKeyword(new_selection)) {
+      ClearKeyword();
+      SetPopupSelection(new_selection);
+    } else if (new_selection.state ==
+               OmniboxPopupSelection::LineState::KEYWORD_MODE) {
+      // Prepare for keyword mode before accepting it.
+      SetPopupSelection(OmniboxPopupSelection(
+          new_selection.line, OmniboxPopupSelection::LineState::NORMAL));
+      // Note: Popup behavior currently depends on the entry method being tab.
+      // This is not ideal for nuanced metrics, but it is how it has worked
+      // for a long time. Consider refactoring to fix this if needed.
+      AcceptKeyword(metrics::OmniboxEventProto::TAB);
+    } else {
+      SetPopupSelection(new_selection);
     }
   } else {
     if (old_selection.IsChangeToKeyword(new_selection)) {
diff --git a/components/omnibox/browser/shortcuts_provider.cc b/components/omnibox/browser/shortcuts_provider.cc
index 4de729e..94d83b9 100644
--- a/components/omnibox/browser/shortcuts_provider.cc
+++ b/components/omnibox/browser/shortcuts_provider.cc
@@ -297,6 +297,14 @@
     if (shortcut_match.relevance == 0)
       continue;
 
+    if (OmniboxFieldTrial::IsKeywordModeRefreshEnabled()) {
+      // Let builtin provider win for starter pack shortcuts; they should not
+      // allow default or inline autocomplete for the keyword mode refresh.
+      if (shortcut_match.type == AutocompleteMatch::Type::STARTER_PACK) {
+        continue;
+      }
+    }
+
     if (shortcut_match.shortcut->match_core.type ==
         AutocompleteMatch::Type::HISTORY_CLUSTER) {
       history_cluster_shortcut_matches.push_back(shortcut_match);
diff --git a/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.cc b/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.cc
index 23a7bd31..6a7ae79 100644
--- a/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.cc
+++ b/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.cc
@@ -6,6 +6,9 @@
 
 #include "base/containers/contains.h"
 #include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/strings/strcat.h"
+#include "base/strings/stringprintf.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
 
@@ -13,6 +16,9 @@
 
 namespace {
 
+// The maximum number of args that can be substituted in the string template.
+static constexpr int kMaxArgs = 32;
+
 std::unique_ptr<proto::OnDeviceModelExecutionConfig>
 ReadOnDeviceModelExecutionConfig(const base::FilePath& path) {
   // Unpack and verify model config file.
@@ -31,6 +37,23 @@
   return std::make_unique<proto::OnDeviceModelExecutionConfig>(config);
 }
 
+std::string StringPrintfVector(const std::string& string_template,
+                               std::vector<std::string> args) {
+  CHECK(args.size() <= kMaxArgs);
+
+  args.resize(kMaxArgs, "");
+  return base::StringPrintfNonConstexpr(
+      string_template.c_str(), args[0].c_str(), args[1].c_str(),
+      args[2].c_str(), args[3].c_str(), args[4].c_str(), args[5].c_str(),
+      args[6].c_str(), args[7].c_str(), args[8].c_str(), args[9].c_str(),
+      args[10].c_str(), args[11].c_str(), args[12].c_str(), args[13].c_str(),
+      args[14].c_str(), args[15].c_str(), args[16].c_str(), args[17].c_str(),
+      args[18].c_str(), args[19].c_str(), args[20].c_str(), args[21].c_str(),
+      args[22].c_str(), args[23].c_str(), args[24].c_str(), args[25].c_str(),
+      args[26].c_str(), args[27].c_str(), args[28].c_str(), args[29].c_str(),
+      args[30].c_str(), args[31].c_str());
+}
+
 }  // namespace
 
 OnDeviceModelExecutionConfigInterpreter::
@@ -83,4 +106,50 @@
   feature_configs_.clear();
 }
 
+absl::optional<std::string>
+OnDeviceModelExecutionConfigInterpreter::ConstructInputString(
+    proto::ModelExecutionFeature feature,
+    const google::protobuf::MessageLite& request) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  // Get the config to construct the input string.
+  if (!HasConfigForFeature(feature)) {
+    return absl::nullopt;
+  }
+  auto feature_config = feature_configs_.at(feature);
+  if (!feature_config.has_input_config()) {
+    return absl::nullopt;
+  }
+  const auto input_config = feature_config.input_config();
+  if (input_config.request_base_name() != request.GetTypeName()) {
+    return absl::nullopt;
+  }
+
+  // TODO(b/302402959): Make sure we have the type mapping?
+
+  // Construct string.
+  std::vector<std::string> substitutions;
+  for (const auto& substitution : input_config.execute_substitutions()) {
+    // TODO(b/302402959): See if conditions apply.
+
+    std::vector<std::string> args;
+    for (const auto& arg : substitution.args()) {
+      // TODO(b/302402959): See if conditions apply.
+
+      if (arg.has_raw_string()) {
+        args.push_back(arg.raw_string());
+      }
+      // TODO(b/302402959): Add support for proto field.
+    }
+    if (static_cast<size_t>(substitution.expected_num_args()) != args.size()) {
+      return absl::nullopt;
+    }
+
+    substitutions.push_back(
+        StringPrintfVector(substitution.string_template(), std::move(args)));
+  }
+
+  return base::StrCat(substitutions);
+}
+
 }  // namespace optimization_guide
diff --git a/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.h b/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.h
index 8d441ea..e0ba4fe 100644
--- a/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.h
+++ b/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter.h
@@ -5,6 +5,7 @@
 #define COMPONENTS_OPTIMIZATION_GUIDE_CORE_MODEL_EXECUTION_ON_DEVICE_MODEL_EXECUTION_CONFIG_INTERPRETER_H_
 
 #include <memory>
+#include <string>
 
 #include "base/containers/flat_map.h"
 #include "base/files/file_path.h"
@@ -13,6 +14,7 @@
 #include "base/sequence_checker.h"
 #include "base/task/sequenced_task_runner.h"
 #include "components/optimization_guide/proto/model_execution.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace optimization_guide {
 
@@ -28,6 +30,13 @@
   // Whether there is an on-device model execution config for `feature`.
   bool HasConfigForFeature(proto::ModelExecutionFeature feature) const;
 
+  // Constructs the input string for `feature` and `request`. Will return
+  // absl::nullopt if there is not a valid config for the feature or the request
+  // could not be fulfilled for any reason.
+  absl::optional<std::string> ConstructInputString(
+      proto::ModelExecutionFeature feature,
+      const google::protobuf::MessageLite& request) const;
+
  private:
   // Populates `feature_configs_` based on `config`.
   void PopulateFeatureConfigs(
diff --git a/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter_unittest.cc b/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter_unittest.cc
index 06e127bc..8f3090a7 100644
--- a/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter_unittest.cc
+++ b/components/optimization_guide/core/model_execution/on_device_model_execution_config_interpreter_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/task_environment.h"
+#include "base/test/test.pb.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -37,6 +38,15 @@
     ASSERT_TRUE(base::WriteFile(file_path, serialized_config));
   }
 
+  void UpdateInterpreterWithConfig(
+      const proto::OnDeviceModelExecutionConfig& config) {
+    WriteConfigToFile(temp_dir().Append(FILE_PATH_LITERAL(
+                          "on_device_model_execution_config.pb")),
+                      config);
+    interpreter()->UpdateConfigWithFileDir(temp_dir());
+    RunUntilIdle();
+  }
+
   void RunUntilIdle() { task_environment_.RunUntilIdle(); }
 
  private:
@@ -114,6 +124,107 @@
   }
 }
 
+TEST_F(OnDeviceModelExecutionConfigInterpeterTest,
+       ConstructInputStringNoOnDeviceConfig) {
+  base::test::TestMessage test;
+  test.set_test("some test");
+  auto maybe_string = interpreter()->ConstructInputString(
+      proto::MODEL_EXECUTION_FEATURE_COMPOSE, test);
+
+  EXPECT_FALSE(maybe_string.has_value());
+}
+
+TEST_F(OnDeviceModelExecutionConfigInterpeterTest,
+       ConstructInputStringNoOnDeviceConfigForFeature) {
+  proto::OnDeviceModelExecutionConfig config;
+  config.add_feature_configs()->set_feature(
+      proto::MODEL_EXECUTION_FEATURE_TAB_ORGANIZATION);
+  UpdateInterpreterWithConfig(config);
+
+  base::test::TestMessage test;
+  test.set_test("some test");
+  auto maybe_string = interpreter()->ConstructInputString(
+      proto::MODEL_EXECUTION_FEATURE_COMPOSE, test);
+
+  EXPECT_FALSE(maybe_string.has_value());
+}
+
+TEST_F(OnDeviceModelExecutionConfigInterpeterTest,
+       ConstructInputStringFeatureConfigExistsButNoInputConfig) {
+  proto::OnDeviceModelExecutionConfig config;
+  config.add_feature_configs()->set_feature(
+      proto::MODEL_EXECUTION_FEATURE_COMPOSE);
+  UpdateInterpreterWithConfig(config);
+
+  base::test::TestMessage test;
+  test.set_test("some test");
+  auto maybe_string = interpreter()->ConstructInputString(
+      proto::MODEL_EXECUTION_FEATURE_COMPOSE, test);
+
+  EXPECT_FALSE(maybe_string.has_value());
+}
+
+TEST_F(OnDeviceModelExecutionConfigInterpeterTest,
+       ConstructInputStringFeatureConfigExistsMismatchRequest) {
+  proto::OnDeviceModelExecutionConfig config;
+  auto* fc = config.add_feature_configs();
+  fc->set_feature(proto::MODEL_EXECUTION_FEATURE_COMPOSE);
+  auto* input_config = fc->mutable_input_config();
+  input_config->set_request_base_name("wrong name");
+  UpdateInterpreterWithConfig(config);
+
+  base::test::TestMessage test;
+  test.set_test("some test");
+  auto maybe_string = interpreter()->ConstructInputString(
+      proto::MODEL_EXECUTION_FEATURE_COMPOSE, test);
+
+  EXPECT_FALSE(maybe_string.has_value());
+}
+
+TEST_F(OnDeviceModelExecutionConfigInterpeterTest,
+       ConstructInputStringFeatureConfigExistsUnexpectedArgsEvaluated) {
+  proto::OnDeviceModelExecutionConfig config;
+  auto* fc = config.add_feature_configs();
+  fc->set_feature(proto::MODEL_EXECUTION_FEATURE_COMPOSE);
+  auto* input_config = fc->mutable_input_config();
+  input_config->set_request_base_name("base.test.TestMessage");
+  auto* substitution = input_config->add_execute_substitutions();
+  substitution->set_string_template("hello this is a %s");
+  substitution->set_expected_num_args(1);
+  substitution->add_args()->set_raw_string("test");
+  substitution->add_args()->set_raw_string("test2");
+  UpdateInterpreterWithConfig(config);
+
+  base::test::TestMessage test;
+  test.set_test("some test");
+  auto maybe_string = interpreter()->ConstructInputString(
+      proto::MODEL_EXECUTION_FEATURE_COMPOSE, test);
+
+  EXPECT_FALSE(maybe_string.has_value());
+}
+
+TEST_F(OnDeviceModelExecutionConfigInterpeterTest,
+       ConstructInputStringFeatureConfigExistsSimpleRawString) {
+  proto::OnDeviceModelExecutionConfig config;
+  auto* fc = config.add_feature_configs();
+  fc->set_feature(proto::MODEL_EXECUTION_FEATURE_COMPOSE);
+  auto* input_config = fc->mutable_input_config();
+  input_config->set_request_base_name("base.test.TestMessage");
+  auto* substitution = input_config->add_execute_substitutions();
+  substitution->set_string_template("hello this is a %s");
+  substitution->set_expected_num_args(1);
+  substitution->add_args()->set_raw_string("test");
+  UpdateInterpreterWithConfig(config);
+
+  base::test::TestMessage test;
+  test.set_test("some test");
+  auto maybe_string = interpreter()->ConstructInputString(
+      proto::MODEL_EXECUTION_FEATURE_COMPOSE, test);
+
+  ASSERT_TRUE(maybe_string);
+  EXPECT_EQ(*maybe_string, "hello this is a test");
+}
+
 }  // namespace
 
 }  // namespace optimization_guide
diff --git a/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc b/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc
index 302b79f..9c97a1d4 100644
--- a/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc
+++ b/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc
@@ -29,20 +29,17 @@
   LaunchService();
   service_remote_->LoadModel(
       on_device_model::LoadModelAssets(model_path_),
+      model_remote_.BindNewPipeAndPassReceiver(),
       base::BindOnce(&OnDeviceModelServiceController::OnLoadModelResult,
-                     weak_ptr_factory_.GetWeakPtr(), input,
-                     std::move(streaming_responder)));
+                     weak_ptr_factory_.GetWeakPtr()));
+  Execute(input, std::move(streaming_responder));
 }
 
 void OnDeviceModelServiceController::OnLoadModelResult(
-    std::string_view input,
-    mojo::PendingRemote<on_device_model::mojom::StreamingResponder>
-        streaming_responder,
-    on_device_model::mojom::LoadModelResultPtr result) {
-  if (result->is_model()) {
-    model_remote_ = mojo::Remote<on_device_model::mojom::OnDeviceModel>(
-        std::move(result->get_model()));
-    Execute(input, std::move(streaming_responder));
+    const std::optional<std::string>& error) {
+  if (error.has_value()) {
+    // TODO(b/302402576): Add error handling.
+    LOG(ERROR) << *error;
   }
 }
 
diff --git a/components/optimization_guide/core/model_execution/on_device_model_service_controller.h b/components/optimization_guide/core/model_execution/on_device_model_service_controller.h
index bf71b4ac..d5a353c8 100644
--- a/components/optimization_guide/core/model_execution/on_device_model_service_controller.h
+++ b/components/optimization_guide/core/model_execution/on_device_model_service_controller.h
@@ -50,11 +50,7 @@
   friend class FakeOnDeviceModelServiceController;
 
   // Invoked at the end of model load, to continue with model execution.
-  void OnLoadModelResult(
-      std::string_view input,
-      mojo::PendingRemote<on_device_model::mojom::StreamingResponder>
-          streaming_responder,
-      on_device_model::mojom::LoadModelResultPtr result);
+  void OnLoadModelResult(const std::optional<std::string>& error);
 
   base::FilePath model_path_;
   mojo::Remote<on_device_model::mojom::OnDeviceModelService> service_remote_;
diff --git a/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc b/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc
index 1c53490..438bf1cb 100644
--- a/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc
+++ b/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc
@@ -42,14 +42,13 @@
     : public on_device_model::mojom::OnDeviceModelService {
  private:
   // on_device_model::mojom::OnDeviceModelService:
-  void LoadModel(on_device_model::ModelAssets assets,
-                 LoadModelCallback callback) override {
-    mojo::PendingRemote<on_device_model::mojom::OnDeviceModel> remote;
+  void LoadModel(
+      on_device_model::ModelAssets assets,
+      mojo::PendingReceiver<on_device_model::mojom::OnDeviceModel> model,
+      LoadModelCallback callback) override {
     auto test_model = std::make_unique<FakeOnDeviceModel>();
-    model_receivers_.Add(std::move(test_model),
-                         remote.InitWithNewPipeAndPassReceiver());
-    std::move(callback).Run(
-        on_device_model::mojom::LoadModelResult::NewModel(std::move(remote)));
+    model_receivers_.Add(std::move(test_model), std::move(model));
+    std::move(callback).Run(std::nullopt);
   }
   void GetEstimatedPerformanceClass(
       GetEstimatedPerformanceClassCallback callback) override {
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal
index ea119ec..8c7276b 160000
--- a/components/optimization_guide/internal
+++ b/components/optimization_guide/internal
@@ -1 +1 @@
-Subproject commit ea119ecea6b7de84e3d431216c0041f3a10c301c
+Subproject commit 8c7276b0b0c1b0aa55e922e6116e314116303e2a
diff --git a/components/optimization_guide/proto/model_execution.proto b/components/optimization_guide/proto/model_execution.proto
index fac93ee..0ed0f639f 100644
--- a/components/optimization_guide/proto/model_execution.proto
+++ b/components/optimization_guide/proto/model_execution.proto
@@ -49,4 +49,47 @@
 message OnDeviceModelExecutionFeatureConfig {
   // The feature this configuration is for.
   optional ModelExecutionFeature feature = 1;
+
+  // The config used to construct the input for on-device model execution.
+  optional OnDeviceModelExecutionInputConfig input_config = 2;
+}
+
+message OnDeviceModelExecutionInputConfig {
+  // The base name of the request metadata proto this input config is applicable
+  // for.
+  optional string request_base_name = 1;
+
+  // TODO(b/302402959): Add support for context substitutions.
+
+  // An ordered list of substituted strings to apply when the model is executed.
+  //
+  // These will be concatenated in the order they appear here if the conditions
+  // apply based on the input request.
+  repeated SubstitutedString execute_substitutions = 2;
+}
+
+message SubstitutedString {
+  // String template with %s as the delimiter for substitutions.
+  optional string string_template = 1;
+
+  // The number of args that are expected to be substituted in the string
+  // template.
+  optional int32 expected_num_args = 2;
+
+  // The arguments to be substituted in `string_template`.
+  repeated StringArg args = 3;
+
+  // TODO(b/302402959): Add support for conditions for which this should be
+  // applied.
+}
+
+message StringArg {
+  oneof arg {
+    string raw_string = 1;
+  }
+
+  // TODO(b/302402959): Add support for max number of characters to apply.
+
+  // TODO(b/302402959): Add support for conditions for which this should be
+  // applied.
 }
diff --git a/components/os_crypt/sync/BUILD.gn b/components/os_crypt/sync/BUILD.gn
index c4bca6fc..445b70c2 100644
--- a/components/os_crypt/sync/BUILD.gn
+++ b/components/os_crypt/sync/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java
index a63b232..521f0fd 100644
--- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java
+++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java
@@ -45,6 +45,7 @@
     private int mAllowedSites;
     private int mBlockedSites;
     private int mStatus;
+    private int mEnforcement;
     private boolean mIsEnforced;
     private long mExpiration;
     private int mConfidenceLevel;
@@ -127,7 +128,7 @@
         params.blockAll3PC = mBlockAll3PC;
         mSubPage.setParams(params);
         if (PageInfoFeatures.USER_BYPASS_UI.isEnabled()) {
-            mSubPage.setCookieStatus(mStatus, mIsEnforced, mExpiration);
+            mSubPage.setCookieStatus(mStatus, mEnforcement, mExpiration);
             mSubPage.setSitesCount(mAllowedSites, mBlockedSites);
         } else {
             mSubPage.setCookieBlockingStatus(mStatus, mIsEnforced);
@@ -222,13 +223,13 @@
     @Override
     public void onStatusChanged(int status, int enforcement, int blockingStatus, long expiration) {
         mStatus = status;
-        mIsEnforced = enforcement != CookieControlsEnforcement.NO_ENFORCEMENT;
+        mEnforcement = enforcement;
         mExpiration = expiration;
 
         updateRowViewSubtitle();
 
         if (mSubPage != null) {
-            mSubPage.setCookieStatus(mStatus, mIsEnforced, expiration);
+            mSubPage.setCookieStatus(mStatus, mEnforcement, expiration);
         }
     }
 
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesSettings.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesSettings.java
index e1124c7f..5a6f6c7 100644
--- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesSettings.java
+++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesSettings.java
@@ -24,6 +24,7 @@
 import org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridge;
 import org.chromium.components.browser_ui.util.date.CalendarUtils;
 import org.chromium.components.content_settings.ContentSettingsType;
+import org.chromium.components.content_settings.CookieControlsEnforcement;
 import org.chromium.components.content_settings.CookieControlsStatus;
 import org.chromium.ui.text.NoUnderlineClickableSpan;
 import org.chromium.ui.text.SpanApplier;
@@ -45,6 +46,7 @@
     private TextMessagePreference mThirdPartyCookiesTitle;
     private TextMessagePreference mThirdPartyCookiesSummary;
     private Runnable mOnClearCallback;
+    private Runnable mOnCookieSettingsLinkClicked;
     private Callback<Activity> mOnFeedbackClicked;
     private Dialog mConfirmationDialog;
     private boolean mDeleteDisabled;
@@ -103,9 +105,14 @@
     public void setParams(PageInfoCookiesViewParams params) {
         mTrackingProtectionUI = params.showTrackingProtectionUI;
         mBlockAll3PC = params.blockAll3PC;
+        mOnCookieSettingsLinkClicked = params.onCookieSettingsLinkClicked;
         Preference cookieSummary = findPreference(COOKIE_SUMMARY_PREFERENCE);
-        NoUnderlineClickableSpan linkSpan = new NoUnderlineClickableSpan(
-                getContext(), (view) -> { params.onCookieSettingsLinkClicked.run(); });
+        NoUnderlineClickableSpan linkSpan =
+                new NoUnderlineClickableSpan(
+                        getContext(),
+                        (view) -> {
+                            mOnCookieSettingsLinkClicked.run();
+                        });
         int summaryString;
         if (mTrackingProtectionUI && mBlockAll3PC) {
             summaryString = R.string.page_info_tracking_protection_blocked_cookies_description;
@@ -189,12 +196,36 @@
 
     // Only used when UserBypassUI flag is on.
     public void setCookieStatus(
-            @CookieControlsStatus int status, final boolean isEnforced, long expiration) {
+            @CookieControlsStatus int status,
+            @CookieControlsEnforcement int enforcement,
+            long expiration) {
         assert PageInfoFeatures.USER_BYPASS_UI.isEnabled()
             : "This should only be invoked when UserBypassUI is enabled.";
 
         boolean visible = status != CookieControlsStatus.DISABLED;
         boolean blockingEnabled = status == CookieControlsStatus.ENABLED;
+        boolean isEnforced = enforcement != CookieControlsEnforcement.NO_ENFORCEMENT;
+
+        if (enforcement == CookieControlsEnforcement.ENFORCED_BY_TPCD_GRANT) {
+            // Hide all the 3PC controls.
+            mCookieSwitch.setVisible(false);
+            mThirdPartyCookiesTitle.setVisible(false);
+            mThirdPartyCookiesSummary.setVisible(false);
+            // TODO(crbug.com/1499873): Move this to the bottom section of the view.
+            Preference cookieSummary = findPreference(COOKIE_SUMMARY_PREFERENCE);
+            NoUnderlineClickableSpan linkSpan =
+                    new NoUnderlineClickableSpan(
+                            getContext(),
+                            (view) -> {
+                                mOnCookieSettingsLinkClicked.run();
+                            });
+            cookieSummary.setSummary(
+                    SpanApplier.applySpans(
+                            getString(
+                                    R.string.page_info_tracking_protection_site_grant_description),
+                            new SpanApplier.SpanInfo("<link>", "</link>", linkSpan)));
+            return;
+        }
 
         mCookieSwitch.setVisible(visible);
         mThirdPartyCookiesTitle.setVisible(visible);
diff --git a/components/page_load_metrics/renderer/DEPS b/components/page_load_metrics/renderer/DEPS
index aea6de1..6799956 100644
--- a/components/page_load_metrics/renderer/DEPS
+++ b/components/page_load_metrics/renderer/DEPS
@@ -9,6 +9,7 @@
   "+ui/gfx/geometry",
   "+url",
   "+mojo/public/cpp/bindings/type_converter.h",
+  "+net/base",
 ]
 
 specific_include_rules = {
diff --git a/components/page_load_metrics/renderer/page_resource_data_use.cc b/components/page_load_metrics/renderer/page_resource_data_use.cc
index b87ede1d..374c19b7 100644
--- a/components/page_load_metrics/renderer/page_resource_data_use.cc
+++ b/components/page_load_metrics/renderer/page_resource_data_use.cc
@@ -4,6 +4,7 @@
 
 #include "components/page_load_metrics/renderer/page_resource_data_use.h"
 
+#include "net/base/proxy_chain.h"
 #include "services/network/public/cpp/url_loader_completion_status.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 #include "third_party/blink/public/common/loader/resource_type_util.h"
@@ -29,7 +30,7 @@
   }
   resource_id_ = resource_id;
 
-  proxy_used_ = !response_head.proxy_server.is_direct();
+  proxy_used_ = !response_head.proxy_chain.is_direct();
   mime_type_ = response_head.mime_type;
   if (response_head.was_fetched_via_cache)
     cache_type_ = mojom::CacheType::kHttp;
diff --git a/components/performance_manager/decorators/freezing_vote_decorator_unittest.cc b/components/performance_manager/decorators/freezing_vote_decorator_unittest.cc
index 851083c..27d0ac9 100644
--- a/components/performance_manager/decorators/freezing_vote_decorator_unittest.cc
+++ b/components/performance_manager/decorators/freezing_vote_decorator_unittest.cc
@@ -36,7 +36,7 @@
 
 TEST_F(FreezingVoteDecoratorTest, VotesAreForwarded) {
   auto page_node = CreateNode<PageNodeImpl>();
-  EXPECT_FALSE(page_node->freezing_vote());
+  EXPECT_FALSE(page_node->GetFreezingVote());
 
   freezing::FreezingVotingChannel voter =
       graph()
@@ -44,19 +44,19 @@
           ->GetVotingChannel();
 
   voter.SubmitVote(page_node.get(), kCannotFreezeVote);
-  ASSERT_TRUE(page_node->freezing_vote().has_value());
-  EXPECT_EQ(kCannotFreezeVote, page_node->freezing_vote().value());
+  ASSERT_TRUE(page_node->GetFreezingVote().has_value());
+  EXPECT_EQ(kCannotFreezeVote, page_node->GetFreezingVote().value());
 
   voter.ChangeVote(page_node.get(), kCanFreezeVote);
-  ASSERT_TRUE(page_node->freezing_vote().has_value());
-  EXPECT_EQ(kCanFreezeVote, page_node->freezing_vote().value());
+  ASSERT_TRUE(page_node->GetFreezingVote().has_value());
+  EXPECT_EQ(kCanFreezeVote, page_node->GetFreezingVote().value());
 
   voter.ChangeVote(page_node.get(), kCannotFreezeVote);
-  ASSERT_TRUE(page_node->freezing_vote().has_value());
-  EXPECT_EQ(kCannotFreezeVote, page_node->freezing_vote().value());
+  ASSERT_TRUE(page_node->GetFreezingVote().has_value());
+  EXPECT_EQ(kCannotFreezeVote, page_node->GetFreezingVote().value());
 
   voter.InvalidateVote(page_node.get());
-  EXPECT_FALSE(page_node->freezing_vote());
+  EXPECT_FALSE(page_node->GetFreezingVote());
 }
 
 }  // namespace performance_manager
diff --git a/components/performance_manager/execution_context/execution_context_impl.cc b/components/performance_manager/execution_context/execution_context_impl.cc
index 986e042..75de6c8 100644
--- a/components/performance_manager/execution_context/execution_context_impl.cc
+++ b/components/performance_manager/execution_context/execution_context_impl.cc
@@ -62,7 +62,7 @@
 
   const GURL& GetUrl() const override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    return node_->url();
+    return node_->GetURL();
   }
 
   const ProcessNode* GetProcessNode() const override {
diff --git a/components/performance_manager/execution_context/execution_context_registry_impl_unittest.cc b/components/performance_manager/execution_context/execution_context_registry_impl_unittest.cc
index 6d295dd..3519b03 100644
--- a/components/performance_manager/execution_context/execution_context_registry_impl_unittest.cc
+++ b/components/performance_manager/execution_context/execution_context_registry_impl_unittest.cc
@@ -100,7 +100,7 @@
   // Expect the FrameExecutionContext implementation to work.
   EXPECT_EQ(ExecutionContextType::kFrameNode, frame1_ec->GetType());
   EXPECT_EQ(frame1->GetFrameToken().value(), frame1_ec->GetToken().value());
-  EXPECT_EQ(frame1->url(), frame1_ec->GetUrl());
+  EXPECT_EQ(frame1->GetURL(), frame1_ec->GetUrl());
   EXPECT_EQ(frame1->process_node(), frame1_ec->GetProcessNode());
   EXPECT_EQ(frame1, frame1_ec->GetFrameNode());
   EXPECT_FALSE(frame1_ec->GetWorkerNode());
@@ -108,7 +108,7 @@
   // Expect the WorkerExecutionContext implementation to work.
   EXPECT_EQ(ExecutionContextType::kWorkerNode, worker_ec->GetType());
   EXPECT_EQ(worker->GetWorkerToken().value(), worker_ec->GetToken().value());
-  EXPECT_EQ(worker->url(), worker_ec->GetUrl());
+  EXPECT_EQ(worker->GetURL(), worker_ec->GetUrl());
   EXPECT_EQ(worker->process_node(), worker_ec->GetProcessNode());
   EXPECT_FALSE(worker_ec->GetFrameNode());
   EXPECT_EQ(worker, worker_ec->GetWorkerNode());
diff --git a/components/performance_manager/graph/frame_node_impl.cc b/components/performance_manager/graph/frame_node_impl.cc
index bd5c9242..835842a 100644
--- a/components/performance_manager/graph/frame_node_impl.cc
+++ b/components/performance_manager/graph/frame_node_impl.cc
@@ -165,7 +165,7 @@
 
 const GURL& FrameNodeImpl::GetURL() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return url();
+  return document_.url.value();
 }
 
 bool FrameNodeImpl::IsCurrent() const {
@@ -316,11 +316,6 @@
   return document_.has_nonempty_beforeunload;
 }
 
-const GURL& FrameNodeImpl::url() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return document_.url.value();
-}
-
 bool FrameNodeImpl::is_current() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return is_current_.value();
diff --git a/components/performance_manager/graph/frame_node_impl.h b/components/performance_manager/graph/frame_node_impl.h
index 708dcd03..ae8cf2b 100644
--- a/components/performance_manager/graph/frame_node_impl.h
+++ b/components/performance_manager/graph/frame_node_impl.h
@@ -119,7 +119,6 @@
   const base::flat_set<PageNodeImpl*>& embedded_page_nodes() const;
   LifecycleState lifecycle_state() const;
   bool has_nonempty_beforeunload() const;
-  const GURL& url() const;
   bool is_current() const;
   bool network_almost_idle() const;
   bool is_ad_frame() const;
diff --git a/components/performance_manager/graph/frame_node_impl_unittest.cc b/components/performance_manager/graph/frame_node_impl_unittest.cc
index 2670505..ea0b750 100644
--- a/components/performance_manager/graph/frame_node_impl_unittest.cc
+++ b/components/performance_manager/graph/frame_node_impl_unittest.cc
@@ -93,20 +93,20 @@
   auto process = CreateNode<ProcessNodeImpl>();
   auto page = CreateNode<PageNodeImpl>();
   auto frame_node = CreateFrameNodeAutoId(process.get(), page.get());
-  EXPECT_TRUE(frame_node->url().is_empty());
+  EXPECT_TRUE(frame_node->GetURL().is_empty());
   const GURL url("http://www.foo.com/");
   frame_node->OnNavigationCommitted(url, /* same_document */ true);
-  EXPECT_EQ(url, frame_node->url());
+  EXPECT_EQ(url, frame_node->GetURL());
 }
 
 TEST_F(FrameNodeImplTest, NavigationCommitted_DifferentDocument) {
   auto process = CreateNode<ProcessNodeImpl>();
   auto page = CreateNode<PageNodeImpl>();
   auto frame_node = CreateFrameNodeAutoId(process.get(), page.get());
-  EXPECT_TRUE(frame_node->url().is_empty());
+  EXPECT_TRUE(frame_node->GetURL().is_empty());
   const GURL url("http://www.foo.com/");
   frame_node->OnNavigationCommitted(url, /* same_document */ false);
-  EXPECT_EQ(url, frame_node->url());
+  EXPECT_EQ(url, frame_node->GetURL());
 }
 
 TEST_F(FrameNodeImplTest, RemoveChildFrame) {
@@ -546,7 +546,6 @@
             public_frame_node->GetLifecycleState());
   EXPECT_EQ(frame_node->has_nonempty_beforeunload(),
             public_frame_node->HasNonemptyBeforeUnload());
-  EXPECT_EQ(frame_node->url(), public_frame_node->GetURL());
   EXPECT_EQ(frame_node->is_current(), public_frame_node->IsCurrent());
   EXPECT_EQ(frame_node->network_almost_idle(),
             public_frame_node->GetNetworkAlmostIdle());
diff --git a/components/performance_manager/graph/page_node_impl.cc b/components/performance_manager/graph/page_node_impl.cc
index 96bb6db..29f2f93 100644
--- a/components/performance_manager/graph/page_node_impl.cc
+++ b/components/performance_manager/graph/page_node_impl.cc
@@ -218,7 +218,7 @@
 const absl::optional<freezing::FreezingVote>& PageNodeImpl::GetFreezingVote()
     const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return freezing_vote();
+  return freezing_vote_.value();
 }
 
 PageState PageNodeImpl::GetPageState() const {
@@ -521,12 +521,6 @@
   return had_user_edits_.value();
 }
 
-const absl::optional<freezing::FreezingVote>& PageNodeImpl::freezing_vote()
-    const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return freezing_vote_.value();
-}
-
 PageNode::PageState PageNodeImpl::page_state() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return page_state_.value();
diff --git a/components/performance_manager/graph/page_node_impl.h b/components/performance_manager/graph/page_node_impl.h
index cd13e38..32e02747 100644
--- a/components/performance_manager/graph/page_node_impl.h
+++ b/components/performance_manager/graph/page_node_impl.h
@@ -169,7 +169,6 @@
   const std::string& contents_mime_type() const;
   bool had_form_interaction() const;
   bool had_user_edits() const;
-  const absl::optional<freezing::FreezingVote>& freezing_vote() const;
   PageState page_state() const;
 
   // Invoked to set/clear the opener of this page.
diff --git a/components/performance_manager/graph/page_node_impl_describer.cc b/components/performance_manager/graph/page_node_impl_describer.cc
index 103cfd95..f12ebb0 100644
--- a/components/performance_manager/graph/page_node_impl_describer.cc
+++ b/components/performance_manager/graph/page_node_impl_describer.cc
@@ -84,7 +84,7 @@
                PageNode::ToString(page_node_impl->embedding_type_));
   }
   result.Set("freezing_vote",
-             FreezingVoteToString(page_node_impl->freezing_vote()));
+             FreezingVoteToString(page_node_impl->GetFreezingVote()));
   result.Set("resource_context",
              page_node_impl->GetResourceContext().ToString());
 
diff --git a/components/performance_manager/graph/page_node_impl_unittest.cc b/components/performance_manager/graph/page_node_impl_unittest.cc
index b7e4a69..bc6f92c 100644
--- a/components/performance_manager/graph/page_node_impl_unittest.cc
+++ b/components/performance_manager/graph/page_node_impl_unittest.cc
@@ -244,14 +244,14 @@
   auto* page_node = mock_graph.page.get();
 
   // This should be initialized to absl::nullopt.
-  EXPECT_FALSE(page_node->freezing_vote());
+  EXPECT_FALSE(page_node->GetFreezingVote());
 
   page_node->set_freezing_vote(kFreezingVote);
-  ASSERT_TRUE(page_node->freezing_vote().has_value());
-  EXPECT_EQ(kFreezingVote, page_node->freezing_vote().value());
+  ASSERT_TRUE(page_node->GetFreezingVote().has_value());
+  EXPECT_EQ(kFreezingVote, page_node->GetFreezingVote().value());
 
   page_node->set_freezing_vote(absl::nullopt);
-  EXPECT_FALSE(page_node->freezing_vote());
+  EXPECT_FALSE(page_node->GetFreezingVote());
 }
 
 namespace {
@@ -420,7 +420,6 @@
   EXPECT_EQ(page_node->main_frame_url(), public_page_node->GetMainFrameUrl());
   EXPECT_EQ(page_node->contents_mime_type(),
             public_page_node->GetContentsMimeType());
-  EXPECT_EQ(page_node->freezing_vote(), public_page_node->GetFreezingVote());
 }
 
 TEST_F(PageNodeImplTest, GetMainFrameNodes) {
diff --git a/components/performance_manager/graph/worker_node_impl.cc b/components/performance_manager/graph/worker_node_impl.cc
index 5f6e25c..5d5e3ac 100644
--- a/components/performance_manager/graph/worker_node_impl.cc
+++ b/components/performance_manager/graph/worker_node_impl.cc
@@ -64,7 +64,7 @@
 
 const GURL& WorkerNodeImpl::GetURL() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return url();
+  return url_;
 }
 
 uint64_t WorkerNodeImpl::GetResidentSetKbEstimate() const {
@@ -180,11 +180,6 @@
   return process_node_;
 }
 
-const GURL& WorkerNodeImpl::url() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return url_;
-}
-
 const base::flat_set<FrameNodeImpl*>& WorkerNodeImpl::client_frames() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return client_frames_;
diff --git a/components/performance_manager/graph/worker_node_impl.h b/components/performance_manager/graph/worker_node_impl.h
index 63338292..51bb794 100644
--- a/components/performance_manager/graph/worker_node_impl.h
+++ b/components/performance_manager/graph/worker_node_impl.h
@@ -75,7 +75,6 @@
   ProcessNodeImpl* process_node() const;
 
   // Getters for non-const properties. These are not thread safe.
-  const GURL& url() const;
   const base::flat_set<FrameNodeImpl*>& client_frames() const;
   const base::flat_set<WorkerNodeImpl*>& client_workers() const;
   const base::flat_set<WorkerNodeImpl*>& child_workers() const;
diff --git a/components/performance_manager/graph/worker_node_impl_describer.cc b/components/performance_manager/graph/worker_node_impl_describer.cc
index abe63fbd..7a7f0abe6 100644
--- a/components/performance_manager/graph/worker_node_impl_describer.cc
+++ b/components/performance_manager/graph/worker_node_impl_describer.cc
@@ -49,7 +49,7 @@
   base::Value::Dict ret;
   ret.Set("browser_context_id", impl->browser_context_id());
   ret.Set("worker_token", impl->GetWorkerToken().ToString());
-  ret.Set("url", impl->url().spec());
+  ret.Set("url", impl->GetURL().spec());
   ret.Set("worker_type", WorkerTypeToString(impl->worker_type()));
   ret.Set("priority", PriorityAndReasonToValue(impl->priority_and_reason()));
   ret.Set("resource_context", impl->GetResourceContext().ToString());
diff --git a/components/performance_manager/graph/worker_node_impl_unittest.cc b/components/performance_manager/graph/worker_node_impl_unittest.cc
index 9dd37b97..dca54475 100644
--- a/components/performance_manager/graph/worker_node_impl_unittest.cc
+++ b/components/performance_manager/graph/worker_node_impl_unittest.cc
@@ -75,11 +75,11 @@
                                                 process.get());
 
   // Initially empty.
-  EXPECT_TRUE(worker_impl->url().is_empty());
+  EXPECT_TRUE(worker_impl->GetURL().is_empty());
 
   // Set when OnFinalResponseURLDetermined() is called.
   worker_impl->OnFinalResponseURLDetermined(kTestUrl);
-  EXPECT_EQ(worker_impl->url(), kTestUrl);
+  EXPECT_EQ(worker_impl->GetURL(), kTestUrl);
 }
 
 // Create a worker of each type and register the frame as a client of each.
diff --git a/components/performance_manager/performance_manager_tab_helper_unittest.cc b/components/performance_manager/performance_manager_tab_helper_unittest.cc
index daf2ff7a..70b2ed6 100644
--- a/components/performance_manager/performance_manager_tab_helper_unittest.cc
+++ b/components/performance_manager/performance_manager_tab_helper_unittest.cc
@@ -126,18 +126,18 @@
     ASSERT_EQ(1u, page->main_frame_nodes().size());
 
     auto* main_frame = page->GetMainFrameNodeImpl();
-    EXPECT_EQ(kParentUrl, main_frame->url().spec());
+    EXPECT_EQ(kParentUrl, main_frame->GetURL().spec());
     EXPECT_EQ(2u, main_frame->child_frame_nodes().size());
 
     for (auto* child_frame : main_frame->child_frame_nodes()) {
-      if (child_frame->url().spec() == kChild1Url) {
+      if (child_frame->GetURL().spec() == kChild1Url) {
         ASSERT_EQ(1u, child_frame->child_frame_nodes().size());
         auto* grandchild_frame = *(child_frame->child_frame_nodes().begin());
-        EXPECT_EQ(grandchild_url, grandchild_frame->url().spec());
-      } else if (child_frame->url().spec() == kChild2Url) {
+        EXPECT_EQ(grandchild_url, grandchild_frame->GetURL().spec());
+      } else if (child_frame->GetURL().spec() == kChild2Url) {
         EXPECT_TRUE(child_frame->child_frame_nodes().empty());
       } else {
-        FAIL() << "Unexpected child frame: " << child_frame->url().spec();
+        FAIL() << "Unexpected child frame: " << child_frame->GetURL().spec();
       }
     }
   });
diff --git a/components/policy/core/common/cloud/device_management_service.cc b/components/policy/core/common/cloud/device_management_service.cc
index b7b6fc5..15f1832 100644
--- a/components/policy/core/common/cloud/device_management_service.cc
+++ b/components/policy/core/common/cloud/device_management_service.cc
@@ -18,6 +18,7 @@
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
+#include "net/base/proxy_chain.h"
 #include "net/base/url_util.h"
 #include "net/http/http_response_headers.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -506,8 +507,8 @@
   std::string mime_type;
   if (url_loader_->ResponseInfo()) {
     was_fetched_via_proxy =
-        url_loader_->ResponseInfo()->proxy_server.is_valid() &&
-        !url_loader_->ResponseInfo()->proxy_server.is_direct();
+        url_loader_->ResponseInfo()->proxy_chain.IsValid() &&
+        !url_loader_->ResponseInfo()->proxy_chain.is_direct();
     mime_type = url_loader_->ResponseInfo()->mime_type;
     if (url_loader_->ResponseInfo()->headers) {
       response_code = url_loader_->ResponseInfo()->headers->response_code();
diff --git a/components/policy/core/common/cloud/device_management_service_unittest.cc b/components/policy/core/common/cloud/device_management_service_unittest.cc
index a326a29..20c29efa 100644
--- a/components/policy/core/common/cloud/device_management_service_unittest.cc
+++ b/components/policy/core/common/cloud/device_management_service_unittest.cc
@@ -25,6 +25,8 @@
 #include "components/policy/core/common/cloud/mock_device_management_service.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
+#include "net/base/proxy_chain.h"
+#include "net/base/proxy_server.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_util.h"
@@ -259,7 +261,7 @@
         net::HttpUtil::AssembleRawHeaders(headers));
 
     if (was_fetched_via_proxy) {
-      head->proxy_server = net::ProxyServer(
+      head->proxy_chain = net::ProxyChain(
           net::ProxyServer::Scheme::SCHEME_HTTPS, /*host_port_pair=*/{});
     }
     head->mime_type = mime_type;
diff --git a/components/policy/test_support/fake_dmserver.cc b/components/policy/test_support/fake_dmserver.cc
index a1a7d72..a085109 100644
--- a/components/policy/test_support/fake_dmserver.cc
+++ b/components/policy/test_support/fake_dmserver.cc
@@ -4,12 +4,14 @@
 
 #include "components/policy/test_support/fake_dmserver.h"
 
+#include <utility>
 #include <vector>
 
 #include "base/base64.h"
 #include "base/files/file_util.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/logging.h"
+#include "base/notreached.h"
 #include "base/scoped_observation.h"
 #include "base/strings/stringprintf.h"
 #include "base/task/bind_post_task.h"
@@ -543,29 +545,28 @@
 
 bool FakeDMServer::ReadPolicyBlobFile() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(embedded_server_sequence_checker_);
-  base::FilePath policy_blob_file(policy_blob_path_);
-  if (!base::PathExists(policy_blob_file)) {
+  if (!base::PathExists(policy_blob_path_)) {
     LOG(INFO) << "Policy blob file doesn't exist yet.";
     return true;
   }
-  JSONFileValueDeserializer deserializer(policy_blob_file);
+  JSONFileValueDeserializer deserializer(policy_blob_path_);
   int error_code = 0;
   std::string error_msg;
   std::unique_ptr<base::Value> value =
       deserializer.Deserialize(&error_code, &error_msg);
   if (!value) {
-    LOG(ERROR) << "Failed to read the policy blob file "
-               << policy_blob_file.value() << ": " << error_msg;
+    LOG(ERROR) << "Failed to read the policy blob file " << policy_blob_path_
+               << ": " << error_msg;
     return false;
   }
   LOG(INFO) << "Deserialized value of the policy blob: " << *value;
-  if (!value->is_dict()) {
+  const base::Value::Dict* dict = value->GetIfDict();
+  if (!dict) {
     LOG(ERROR) << "Policy blob isn't a dict";
     return false;
   }
-  base::Value::Dict& dict = value->GetDict();
 
-  std::string* policy_user = dict.FindString(kPolicyUserKey);
+  const std::string* policy_user = dict->FindString(kPolicyUserKey);
   if (policy_user) {
     LOG(INFO) << "Adding " << *policy_user << " as a policy user";
     policy_storage()->set_policy_user(*policy_user);
@@ -575,7 +576,7 @@
               << policy::kDefaultUsername << " will be used";
   }
 
-  base::Value::List* managed_users = dict.FindList(kManagedUsersKey);
+  const base::Value::List* managed_users = dict->FindList(kManagedUsersKey);
   if (managed_users) {
     for (const base::Value& managed_user : *managed_users) {
       const std::string* managed_val = managed_user.GetIfString();
@@ -586,8 +587,8 @@
     }
   }
 
-  base::Value::List* device_affiliation_ids =
-      dict.FindList(kDeviceAffiliationIdsKey);
+  const base::Value::List* device_affiliation_ids =
+      dict->FindList(kDeviceAffiliationIdsKey);
   if (device_affiliation_ids) {
     for (const base::Value& device_affiliation_id : *device_affiliation_ids) {
       const std::string* device_affiliation_id_val =
@@ -600,8 +601,8 @@
     }
   }
 
-  base::Value::List* user_affiliation_ids =
-      dict.FindList(kUserAffiliationIdsKey);
+  const base::Value::List* user_affiliation_ids =
+      dict->FindList(kUserAffiliationIdsKey);
   if (user_affiliation_ids) {
     for (const base::Value& user_affiliation_id : *user_affiliation_ids) {
       const std::string* user_affiliation_id_val =
@@ -614,17 +615,15 @@
     }
   }
 
-  std::string* directory_api_id = dict.FindString(kDirectoryApiIdKey);
+  const std::string* directory_api_id = dict->FindString(kDirectoryApiIdKey);
   if (directory_api_id) {
     LOG(INFO) << "Adding " << *directory_api_id << " as a directory API ID";
     policy_storage()->set_directory_api_id(*directory_api_id);
   }
 
-  if (dict.contains(kAllowSetDeviceAttributesKey)) {
-    absl::optional<bool> allow_set_device_attributes =
-        dict.FindBool(kAllowSetDeviceAttributesKey);
+  if (const base::Value* v = dict->Find(kAllowSetDeviceAttributesKey); v) {
+    absl::optional<bool> allow_set_device_attributes = v->GetIfBool();
     if (!allow_set_device_attributes.has_value()) {
-      base::Value* v = dict.Find(kAllowSetDeviceAttributesKey);
       LOG(ERROR)
           << "The allow_set_device_attributes key isn't a bool, found type "
           << v->type() << ", found value " << *v;
@@ -634,29 +633,31 @@
         allow_set_device_attributes.value());
   }
 
-  base::Value* use_universal_signing_keys =
-      dict.Find(kUseUniversalSigningKeysKey);
+  const base::Value* use_universal_signing_keys =
+      dict->Find(kUseUniversalSigningKeysKey);
   if (use_universal_signing_keys) {
-    if (!use_universal_signing_keys->is_bool()) {
+    absl::optional<bool> maybe_value = use_universal_signing_keys->GetIfBool();
+    if (!maybe_value.has_value()) {
       LOG(ERROR)
           << "The use_universal_signing_keys key isn't a bool, found type "
           << use_universal_signing_keys->type() << ", found value "
           << *use_universal_signing_keys;
       return false;
     }
-    if (use_universal_signing_keys->GetBool()) {
+    if (maybe_value.value()) {
       policy_storage()->signature_provider()->SetUniversalSigningKeys();
     }
   }
 
-  std::string* robot_api_auth_code = dict.FindString(kRobotApiAuthCodeKey);
+  const std::string* robot_api_auth_code =
+      dict->FindString(kRobotApiAuthCodeKey);
   if (robot_api_auth_code) {
     LOG(INFO) << "Adding " << *robot_api_auth_code
               << " as a robot api auth code";
     policy_storage()->set_robot_api_auth_code(*robot_api_auth_code);
   }
 
-  base::Value::Dict* request_errors = dict.FindDict(kRequestErrorsKey);
+  const base::Value::Dict* request_errors = dict->FindDict(kRequestErrorsKey);
   if (request_errors) {
     for (auto request_error : *request_errors) {
       absl::optional<int> net_error_code = request_error.second.GetIfInt();
@@ -672,25 +673,24 @@
     }
   }
 
-  base::Value::Dict* initial_enrollment_state =
-      dict.FindDict(kInitialEnrollmentStateKey);
+  const base::Value::Dict* initial_enrollment_state =
+      dict->FindDict(kInitialEnrollmentStateKey);
   if (initial_enrollment_state) {
-    for (base::detail::dict_iterator::reference state :
-         *initial_enrollment_state) {
-      if (!state.second.is_dict()) {
+    for (auto state : *initial_enrollment_state) {
+      const base::Value::Dict* state_val = state.second.GetIfDict();
+      if (!state_val) {
         LOG(ERROR) << "The current state value for key " << state.first
                    << " isn't a dict";
         return false;
       }
-      base::Value::Dict& state_val = state.second.GetDict();
-      std::string* management_domain =
-          state_val.FindString(kManagementDomainKey);
+      const std::string* management_domain =
+          state_val->FindString(kManagementDomainKey);
       if (!management_domain) {
         LOG(ERROR) << "The management_domain key isn't a string";
         return false;
       }
       absl::optional<int> initial_enrollment_mode =
-          state_val.FindInt(kInitialEnrollmentModeKey);
+          state_val->FindInt(kInitialEnrollmentModeKey);
       if (!initial_enrollment_mode.has_value()) {
         LOG(ERROR) << "The initial_enrollment_mode key isn't an int";
         return false;
@@ -704,10 +704,9 @@
     }
   }
 
-  if (dict.contains(kCurrentKeyIndexKey)) {
-    absl::optional<int> current_key_index = dict.FindInt(kCurrentKeyIndexKey);
+  if (const base::Value* v = dict->Find(kCurrentKeyIndexKey); v) {
+    absl::optional<int> current_key_index = v->GetIfInt();
     if (!current_key_index.has_value()) {
-      base::Value* v = dict.Find(kCurrentKeyIndexKey);
       LOG(ERROR) << "The current_key_index key isn't an int, found type "
                  << v->type() << ", found value " << *v;
       return false;
@@ -716,33 +715,36 @@
         current_key_index.value());
   }
 
-  base::Value::List* policies = dict.FindList(kPoliciesKey);
+  const base::Value::List* policies = dict->FindList(kPoliciesKey);
   if (policies) {
     for (const base::Value& policy : *policies) {
-      if (!policy.is_dict()) {
+      const base::Value::Dict* policy_as_dict = policy.GetIfDict();
+      if (!policy_as_dict) {
         LOG(ERROR) << "The current policy isn't a dict";
         return false;
       }
-      if (!SetPolicyPayload(policy.GetDict().FindString(kPolicyTypeKey),
-                            policy.GetDict().FindString(kEntityIdKey),
-                            policy.GetDict().FindString(kPolicyValueKey))) {
+      if (!SetPolicyPayload(policy_as_dict->FindString(kPolicyTypeKey),
+                            policy_as_dict->FindString(kEntityIdKey),
+                            policy_as_dict->FindString(kPolicyValueKey))) {
         LOG(ERROR) << "Failed to set the policy";
         return false;
       }
     }
   }
 
-  base::Value::List* external_policies = dict.FindList(kExternalPoliciesKey);
+  const base::Value::List* external_policies =
+      dict->FindList(kExternalPoliciesKey);
   if (external_policies) {
     for (const base::Value& policy : *external_policies) {
-      if (!policy.is_dict()) {
+      const base::Value::Dict* policy_as_dict = policy.GetIfDict();
+      if (!policy_as_dict) {
         LOG(ERROR) << "The current external policy isn't a dict";
         return false;
       }
       if (!SetExternalPolicyPayload(
-              policy.GetDict().FindString(kPolicyTypeKey),
-              policy.GetDict().FindString(kEntityIdKey),
-              policy.GetDict().FindString(kPolicyValueKey))) {
+              policy_as_dict->FindString(kPolicyTypeKey),
+              policy_as_dict->FindString(kEntityIdKey),
+              policy_as_dict->FindString(kPolicyValueKey))) {
         LOG(ERROR) << "Failed to set the external policy";
         return false;
       }
@@ -773,7 +775,6 @@
 
 bool FakeDMServer::WriteClientStateFile() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(embedded_server_sequence_checker_);
-  base::FilePath client_state_file(client_state_path_);
   std::vector<policy::ClientStorage::ClientInfo> clients =
       client_storage()->GetAllClients();
   base::Value::Dict dict_clients;
@@ -781,7 +782,7 @@
     dict_clients.Set(c.device_id, GetValueFromClient(c));
   }
 
-  JSONFileValueSerializer serializer(client_state_file);
+  JSONFileValueSerializer serializer(client_state_path_);
   return serializer.Serialize(base::ValueView(dict_clients));
 }
 
@@ -806,8 +807,7 @@
       return true;
     }
     default: {
-      NOTREACHED() << "Unsupported type for client file key";
-      return false;
+      NOTREACHED_NORETURN() << "Unsupported type for client file key";
     }
   }
 }
@@ -815,26 +815,26 @@
 absl::optional<policy::ClientStorage::ClientInfo>
 FakeDMServer::GetClientFromValue(const base::Value& v) {
   policy::ClientStorage::ClientInfo client_info;
-  if (!v.is_dict()) {
+  const base::Value::Dict* dict = v.GetIfDict();
+  if (!dict) {
     LOG(ERROR) << "Client value isn't a dict";
     return absl::nullopt;
   }
 
-  const base::Value::Dict& dict = v.GetDict();
-  if (!FindKey(dict, kDeviceIdKey, base::Value::Type::STRING) ||
-      !FindKey(dict, kDeviceTokenKey, base::Value::Type::STRING) ||
-      !FindKey(dict, kMachineNameKey, base::Value::Type::STRING) ||
-      !FindKey(dict, kUsernameKey, base::Value::Type::STRING) ||
-      !FindKey(dict, kStateKeysKey, base::Value::Type::LIST) ||
-      !FindKey(dict, kAllowedPolicyTypesKey, base::Value::Type::LIST)) {
+  if (!FindKey(*dict, kDeviceIdKey, base::Value::Type::STRING) ||
+      !FindKey(*dict, kDeviceTokenKey, base::Value::Type::STRING) ||
+      !FindKey(*dict, kMachineNameKey, base::Value::Type::STRING) ||
+      !FindKey(*dict, kUsernameKey, base::Value::Type::STRING) ||
+      !FindKey(*dict, kStateKeysKey, base::Value::Type::LIST) ||
+      !FindKey(*dict, kAllowedPolicyTypesKey, base::Value::Type::LIST)) {
     return absl::nullopt;
   }
 
-  client_info.device_id = *dict.FindString(kDeviceIdKey);
-  client_info.device_token = *dict.FindString(kDeviceTokenKey);
-  client_info.machine_name = *dict.FindString(kMachineNameKey);
-  client_info.username = *dict.FindString(kUsernameKey);
-  const base::Value::List* state_keys = dict.FindList(kStateKeysKey);
+  client_info.device_id = *dict->FindString(kDeviceIdKey);
+  client_info.device_token = *dict->FindString(kDeviceTokenKey);
+  client_info.machine_name = *dict->FindString(kMachineNameKey);
+  client_info.username = *dict->FindString(kUsernameKey);
+  const base::Value::List* state_keys = dict->FindList(kStateKeysKey);
   for (const auto& it : *state_keys) {
     const std::string* key = it.GetIfString();
     if (!key) {
@@ -843,7 +843,8 @@
     }
     client_info.state_keys.emplace_back(*key);
   }
-  const base::Value::List* policy_types = dict.FindList(kAllowedPolicyTypesKey);
+  const base::Value::List* policy_types =
+      dict->FindList(kAllowedPolicyTypesKey);
   for (const auto& it : *policy_types) {
     const std::string* key = it.GetIfString();
     if (!key) {
@@ -857,27 +858,26 @@
 
 bool FakeDMServer::ReadClientStateFile() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(embedded_server_sequence_checker_);
-  base::FilePath client_state_file(client_state_path_);
-  if (!base::PathExists(client_state_file)) {
+  if (!base::PathExists(client_state_path_)) {
     LOG(INFO) << "Client state file doesn't exist yet.";
     return true;
   }
-  JSONFileValueDeserializer deserializer(client_state_file);
+  JSONFileValueDeserializer deserializer(client_state_path_);
   int error_code = 0;
   std::string error_msg;
   std::unique_ptr<base::Value> value =
       deserializer.Deserialize(&error_code, &error_msg);
   if (!value) {
-    LOG(ERROR) << "Failed to read client state file "
-               << client_state_file.value() << ": " << error_msg;
+    LOG(ERROR) << "Failed to read client state file " << client_state_path_
+               << ": " << error_msg;
     return false;
   }
-  if (!value->is_dict()) {
+  const base::Value::Dict* dict = value->GetIfDict();
+  if (!dict) {
     LOG(ERROR) << "The client state file isn't a dict.";
     return false;
   }
-  base::Value::Dict& dict = value->GetDict();
-  for (auto it : dict) {
+  for (auto it : *dict) {
     absl::optional<policy::ClientStorage::ClientInfo> c =
         GetClientFromValue(it.second);
     if (!c.has_value()) {
diff --git a/components/policy/test_support/fake_dmserver.h b/components/policy/test_support/fake_dmserver.h
index 932e287a..46b7fad 100644
--- a/components/policy/test_support/fake_dmserver.h
+++ b/components/policy/test_support/fake_dmserver.h
@@ -2,6 +2,27 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_POLICY_TEST_SUPPORT_FAKE_DMSERVER_H_
+#define COMPONENTS_POLICY_TEST_SUPPORT_FAKE_DMSERVER_H_
+
+#include <memory>
+#include <set>
+#include <string>
+
+#include "base/command_line.h"
+#include "base/containers/unique_ptr_adapters.h"
+#include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/values.h"
+#include "chromecast/cast_core/grpc/grpc_server.h"
+#include "chromecast/cast_core/grpc/grpc_unary_handler.h"
+#include "components/policy/test_support/client_storage.h"
+#include "components/policy/test_support/embedded_policy_test_server.h"
+#include "components/policy/test_support/remote_commands_service.castcore.pb.h"  // NOLINT(build/include_directory)
+#include "components/policy/test_support/remote_commands_state.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
 /*
 A bare-bones test server for testing cloud policy support.
 
@@ -74,26 +95,6 @@
 }
 */
 
-#ifndef COMPONENTS_POLICY_TEST_SUPPORT_FAKE_DMSERVER_H_
-#define COMPONENTS_POLICY_TEST_SUPPORT_FAKE_DMSERVER_H_
-
-#include <set>
-#include <string>
-
-#include "base/command_line.h"
-#include "base/containers/unique_ptr_adapters.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequence_checker.h"
-#include "base/timer/timer.h"
-#include "base/values.h"
-#include "chromecast/cast_core/grpc/grpc_server.h"
-#include "chromecast/cast_core/grpc/grpc_unary_handler.h"
-#include "components/policy/test_support/client_storage.h"
-#include "components/policy/test_support/embedded_policy_test_server.h"
-#include "components/policy/test_support/remote_commands_service.castcore.pb.h"  // NOLINT(build/include_directory)
-#include "components/policy/test_support/remote_commands_state.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-
 namespace fakedms {
 
 void InitLogging(const absl::optional<std::string>& log_path,
@@ -225,8 +226,8 @@
   // Erase the wait operation from the waiters_ set.
   void EraseWaitOperation(RemoteCommandsWaitOperation*);
 
-  std::string policy_blob_path_;
-  std::string client_state_path_;
+  const base::FilePath policy_blob_path_;
+  const base::FilePath client_state_path_;
   std::string grpc_unix_socket_uri_;
 
   // Sequence checker for fake_dmserver main IO thread.
diff --git a/components/policy/test_support/fake_dmserver_main.cc b/components/policy/test_support/fake_dmserver_main.cc
index 76d968c4..a9321fe0 100644
--- a/components/policy/test_support/fake_dmserver_main.cc
+++ b/components/policy/test_support/fake_dmserver_main.cc
@@ -2,7 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <string>
+#include <utility>
+
 #include "base/command_line.h"
+#include "base/files/scoped_file.h"
 #include "base/run_loop.h"
 #include "base/task/single_thread_task_executor.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
@@ -13,7 +17,9 @@
   base::ThreadPoolInstance::CreateAndStartWithDefaultParams("fake_dmserver");
   base::CommandLine::Init(argc, argv);
 
-  std::string policy_blob_path, client_state_path, unix_socket_path;
+  std::string policy_blob_path;
+  std::string client_state_path;
+  std::string unix_socket_path;
   absl::optional<std::string> log_path;
   base::ScopedFD startup_pipe;
   int min_log_level;
diff --git a/components/safe_browsing/buildflags.gni b/components/safe_browsing/buildflags.gni
index 3728937..2315578c 100644
--- a/components/safe_browsing/buildflags.gni
+++ b/components/safe_browsing/buildflags.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 if (is_android) {
   import("//build/config/android/config.gni")
 }
diff --git a/components/safe_browsing/content/browser/threat_details_cache.cc b/components/safe_browsing/content/browser/threat_details_cache.cc
index f0964ad..53f0b1e 100644
--- a/components/safe_browsing/content/browser/threat_details_cache.cc
+++ b/components/safe_browsing/content/browser/threat_details_cache.cc
@@ -18,6 +18,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
+#include "net/base/proxy_chain.h"
 #include "net/http/http_response_headers.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/resource_request.h"
@@ -202,8 +203,8 @@
   }
 
   bool was_fetched_via_proxy =
-      current_load_->ResponseInfo()->proxy_server.is_valid() &&
-      !current_load_->ResponseInfo()->proxy_server.is_direct();
+      current_load_->ResponseInfo()->proxy_chain.IsValid() &&
+      !current_load_->ResponseInfo()->proxy_chain.is_direct();
   if (!was_fetched_via_proxy) {
     pb_response->set_remote_ip(
         current_load_->ResponseInfo()->remote_endpoint.ToString());
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.cc b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.cc
index 8d8108320..d50bc1d 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.cc
+++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.cc
@@ -66,11 +66,6 @@
 
   classifier_.reset(classifier);
 
-  model_version_ =
-      classifier_->is_ready()
-          ? ScorerStorage::GetInstance()->GetScorer()->model_version()
-          : 0;
-
   render_frame->GetAssociatedInterfaceRegistry()
       ->AddInterface<mojom::PhishingDetector>(base::BindRepeating(
           &PhishingClassifierDelegate::PhishingDetectorReceiver,
@@ -298,21 +293,8 @@
     return;
   }
 
-  // When a scorer is updated, we want to make sure that the model version is
-  // updated. When the user restarts their browser, their scorer could be
-  // changed twice due to the image embedding model polled from
-  // OptimizationGuide server shortly afterwards, and this can interfere with
-  // the first classification happening.
-  if (model_version_ == scorer->model_version()) {
-    return;
-  }
-
-  model_version_ = scorer->model_version();
-
-  // If the model version has changed, we should cancel any pending
-  // classification if there is one. We check |is_classifying_| here because
-  // |CancelPendingClassification| clears the page text, and we do not want that
-  // if we are awaiting retry.
+  // We check |is_classifying_| here because |CancelPendingClassification|
+  // clears the page text, and we do not want that if we are awaiting retry.
   if (is_classifying_) {
     CancelPendingClassification(NEW_PHISHING_SCORER);
   } else if (awaiting_retry_) {
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.h b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.h
index 3923e00..199552a2 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.h
+++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.h
@@ -164,11 +164,6 @@
   // Set to true if the classifier is currently running.
   bool is_classifying_;
 
-  // This is to track the current model version we are using to classify. This
-  // is so that when the Scorer update changes and there is a classification
-  // going on, we do not cancel when the version hasn't changed.
-  int model_version_;
-
   // Set to true when StartPhishingDetection method is called. It is
   // set to false whenever phishing detection has finished.
   bool is_phishing_detection_running_ = false;
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc b/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
index d129330a..ba9c595 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
+++ b/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
@@ -501,7 +501,6 @@
     base::OnceCallback<void(std::vector<double>)> callback) const {
   DCHECK(content::RenderThread::IsMainThread());
   if (visual_tflite_model_.IsValid()) {
-    base::Time start_post_task_time = base::Time::Now();
     base::ThreadPool::PostTask(
         FROM_HERE, {base::TaskPriority::BEST_EFFORT},
         base::BindOnce(&ApplyVisualTfLiteModelHelper, bitmap,
@@ -512,9 +511,6 @@
                                    visual_tflite_model_.length()),
                        base::SequencedTaskRunner::GetCurrentDefault(),
                        std::move(callback)));
-    base::UmaHistogramTimes(
-        "SBClientPhishing.TfLiteModelLoadTime.FlatbufferScorer",
-        base::Time::Now() - start_post_task_time);
   } else {
     std::move(callback).Run(std::vector<double>());
   }
diff --git a/components/services/app_service/public/cpp/BUILD.gn b/components/services/app_service/public/cpp/BUILD.gn
index a6a9170..ec3465e 100644
--- a/components/services/app_service/public/cpp/BUILD.gn
+++ b/components/services/app_service/public/cpp/BUILD.gn
@@ -330,6 +330,7 @@
       "instance_unittest.cc",
       "instance_update_unittest.cc",
       "permission_unittest.cc",
+      "run_on_os_login_types_unittest.cc",
     ]
 
     deps += [
diff --git a/components/services/app_service/public/cpp/app_storage/app_storage.cc b/components/services/app_service/public/cpp/app_storage/app_storage.cc
index b2003ef..affd68c7 100644
--- a/components/services/app_service/public/cpp/app_storage/app_storage.cc
+++ b/components/services/app_service/public/cpp/app_storage/app_storage.cc
@@ -134,6 +134,7 @@
 
   IS_APP_VALUE_CHANGED(name);
   IS_APP_VALUE_CHANGED(short_name);
+  IS_APP_VALUE_CHANGED(publisher_id);
   IS_APP_VALUE_CHANGED(description);
   IS_APP_VALUE_CHANGED(version);
 
@@ -191,6 +192,8 @@
 
   IS_APP_VALUE_CHANGED_FOR_ENUM(window_mode, WindowMode::kUnknown)
 
+  IS_APP_VALUE_CHANGED(run_on_os_login)
+
   // TODO(crbug.com/1385932): Add other files in the App structure.
   return false;
 }
diff --git a/components/services/app_service/public/cpp/app_storage/app_storage_file_handler.cc b/components/services/app_service/public/cpp/app_storage/app_storage_file_handler.cc
index 5433d8d..0cc94f3 100644
--- a/components/services/app_service/public/cpp/app_storage/app_storage_file_handler.cc
+++ b/components/services/app_service/public/cpp/app_storage/app_storage_file_handler.cc
@@ -14,6 +14,7 @@
 #include "components/services/app_service/public/cpp/icon_effects.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
 #include "components/services/app_service/public/cpp/permission.h"
+#include "components/services/app_service/public/cpp/run_on_os_login_types.h"
 
 namespace apps {
 
@@ -28,6 +29,7 @@
 constexpr char kReadinessKey[] = "readiness";
 constexpr char kNameKey[] = "name";
 constexpr char kShortNameKey[] = "short_name";
+constexpr char kPublisherIdKey[] = "publisher_id";
 constexpr char kDescriptionKey[] = "description";
 constexpr char kVersionKey[] = "version";
 constexpr char kAdditionalSearchTermsKey[] = "additional_search_terms";
@@ -50,6 +52,7 @@
 constexpr char kAllowUninstallKey[] = "allow_uninstall";
 constexpr char kIntentFiltersKey[] = "intent_filters";
 constexpr char kWindowModeKey[] = "window_mode";
+constexpr char kRunOnOsLoginKey[] = "run_on_os_login";
 
 absl::optional<std::string> GetStringValueFromDict(
     const base::Value::Dict& dict,
@@ -114,6 +117,12 @@
   return base::Value(ConvertPermissionsToList(app.get()->*field));
 }
 
+template <>
+base::Value GetValue(const AppPtr& app,
+                     absl::optional<RunOnOsLogin> App::*field) {
+  return base::Value(ConvertRunOnOsLoginToDict((app.get()->*field).value()));
+}
+
 template <typename T>
 void SetKey(const AppPtr& app,
             T App::*field,
@@ -215,6 +224,7 @@
     SetKey(app, &App::readiness, kReadinessKey, dict);
     SetKey(app, &App::name, kNameKey, dict);
     SetKey(app, &App::short_name, kShortNameKey, dict);
+    SetKey(app, &App::publisher_id, kPublisherIdKey, dict);
     SetKey(app, &App::description, kDescriptionKey, dict);
     SetKey(app, &App::version, kVersionKey, dict);
     SetKey(app, &App::additional_search_terms, kAdditionalSearchTermsKey, dict);
@@ -247,6 +257,7 @@
     SetKey(app, &App::allow_uninstall, kAllowUninstallKey, dict);
     SetKey(app, &App::intent_filters, kIntentFiltersKey, dict);
     SetKey(app, &App::window_mode, kWindowModeKey, dict);
+    SetKey(app, &App::run_on_os_login, kRunOnOsLoginKey, dict);
 
     // TODO(crbug.com/1385932): Add other files in the App structure.
     app_info_dict.Set(app->app_id, std::move(dict));
@@ -291,6 +302,7 @@
 
     app->name = GetStringValueFromDict(*value, kNameKey);
     app->short_name = GetStringValueFromDict(*value, kShortNameKey);
+    app->publisher_id = GetStringValueFromDict(*value, kPublisherIdKey);
     app->description = GetStringValueFromDict(*value, kDescriptionKey);
     app->version = GetStringValueFromDict(*value, kVersionKey);
 
@@ -364,6 +376,9 @@
 
     GetEnumFromKey(value, &App::window_mode, kWindowModeKey, app);
 
+    app->run_on_os_login =
+        ConvertDictToRunOnOsLogin(value->FindDict(kRunOnOsLoginKey));
+
     // TODO(crbug.com/1385932): Add other files in the App structure.
     app_info->apps.push_back(std::move(app));
     app_info->app_types.insert(static_cast<AppType>(app_type.value()));
diff --git a/components/services/app_service/public/cpp/app_storage/app_storage_file_handler_unittest.cc b/components/services/app_service/public/cpp/app_storage/app_storage_file_handler_unittest.cc
index 14f09ff..1b66afc 100644
--- a/components/services/app_service/public/cpp/app_storage/app_storage_file_handler_unittest.cc
+++ b/components/services/app_service/public/cpp/app_storage/app_storage_file_handler_unittest.cc
@@ -112,6 +112,7 @@
     app2->readiness = Readiness::kDisabledByUser;
     app2->name = kAppName2;
     app2->short_name = kAppShortName;
+    app2->publisher_id = "publisher_id";
     app2->description = "description";
     app2->version = "version";
     app2->additional_search_terms = {"item1", "item2"};
@@ -144,6 +145,8 @@
     app2->intent_filters.push_back(apps_util::MakeIntentFilterForUrlScope(
         GURL("https://www.google.com/abc")));
     app2->window_mode = WindowMode::kBrowser;
+    app2->run_on_os_login = RunOnOsLogin(RunOnOsLoginMode::kNotRun,
+                                         /*is_managed=*/true);
     apps.push_back(std::move(app2));
 
     // TODO(crbug.com/1385932): Add other files in the App structure.
diff --git a/components/services/app_service/public/cpp/app_storage/app_storage_unittest.cc b/components/services/app_service/public/cpp/app_storage/app_storage_unittest.cc
index 3ea6134..89bfb0b0 100644
--- a/components/services/app_service/public/cpp/app_storage/app_storage_unittest.cc
+++ b/components/services/app_service/public/cpp/app_storage/app_storage_unittest.cc
@@ -168,6 +168,7 @@
     app2->readiness = kReadiness2;
     app2->name = kAppName2;
     app2->short_name = kAppShortName1;
+    app2->publisher_id = "publisher_id";
     app2->description = "description";
     app2->version = "version";
     app2->additional_search_terms = {"term1", "term2"};
@@ -199,6 +200,10 @@
     app2->paused = false;
     app2->intent_filters.push_back(apps_util::MakeIntentFilterForUrlScope(
         GURL("https://www.google.com/abc")));
+    app2->window_mode = WindowMode::kBrowser;
+    app2->run_on_os_login = RunOnOsLogin(RunOnOsLoginMode::kNotRun,
+                                         /*is_managed=*/false);
+
     apps.push_back(std::move(app2));
 
     // TODO(crbug.com/1385932): Add other files in the App structure.
@@ -208,6 +213,7 @@
   MODIFY_FIELD(name, kAppName2)
   MODIFY_FIELD(short_name, kAppShortName2)
   MODIFY_FIELD(description, "description")
+  MODIFY_FIELD(publisher_id, "publisher_id")
   MODIFY_FIELD(version, "version")
   MODIFY_FIELD(additional_search_terms, {"term1"})
   MODIFY_FIELD(last_launch_time, base::Time() + base::Days(2))
@@ -224,6 +230,9 @@
   MODIFY_FIELD(show_in_management, true)
   MODIFY_FIELD(handles_intents, false)
   MODIFY_FIELD(allow_uninstall, false)
+  MODIFY_FIELD(window_mode, WindowMode::kWindow)
+  MODIFY_FIELD(run_on_os_login,
+               RunOnOsLogin(RunOnOsLoginMode::kNotRun, /*is_managed=*/false))
 
   void ModifyIconKey(absl::optional<IconKey> icon_key) {
     AppPtr app = std::make_unique<App>(kAppType1, kAppId1);
@@ -369,6 +378,7 @@
 
   VERIFY_MODIFY_FIELD(name, kAppName2);
   VERIFY_MODIFY_FIELD(short_name, kAppShortName2);
+  VERIFY_MODIFY_FIELD(publisher_id, "publisher_id");
   VERIFY_MODIFY_FIELD(description, "description");
   VERIFY_MODIFY_FIELD(version, "version");
   VERIFY_MODIFY_FIELD(additional_search_terms, {"term1"});
@@ -386,6 +396,9 @@
   VERIFY_MODIFY_FIELD(show_in_management, true);
   VERIFY_MODIFY_FIELD(handles_intents, false);
   VERIFY_MODIFY_FIELD(allow_uninstall, false);
+  VERIFY_MODIFY_FIELD(window_mode, WindowMode::kWindow);
+  VERIFY_MODIFY_FIELD(run_on_os_login, RunOnOsLogin(RunOnOsLoginMode::kNotRun,
+                                                    /*is_managed=*/false));
 
   // Verify for the none icon effect.
   IconKey icon_key1(IconEffects::kNone);
diff --git a/components/services/app_service/public/cpp/app_types.h b/components/services/app_service/public/cpp/app_types.h
index 49cb4aa..a09ff6a3 100644
--- a/components/services/app_service/public/cpp/app_types.h
+++ b/components/services/app_service/public/cpp/app_types.h
@@ -236,7 +236,11 @@
   absl::optional<std::string> selected_locale;
 
   // When adding new fields to the App type, the `Clone` function, the
-  // `operator==` function, and the `AppUpdate` class should also be updated.
+  // `operator==` function, and the `AppUpdate` class should also be updated. If
+  // the new fields should be saved, below functions should be updated:
+  // `AppStorage::IsAppChanged`
+  // `AppStorageFileHandler::ConvertAppsToValue`
+  // `AppStorageFileHandler::ConvertValueToApps`
 };
 
 using AppPtr = std::unique_ptr<App>;
diff --git a/components/services/app_service/public/cpp/permission.cc b/components/services/app_service/public/cpp/permission.cc
index 4907a7a..73035c0 100644
--- a/components/services/app_service/public/cpp/permission.cc
+++ b/components/services/app_service/public/cpp/permission.cc
@@ -130,7 +130,9 @@
 
 PermissionPtr ConvertDictToPermission(const base::Value::Dict& dict) {
   absl::optional<int> permission_type = dict.FindInt(kPermissionTypeKey);
-  if (!permission_type.has_value()) {
+  if (!permission_type.has_value() ||
+      permission_type.value() < static_cast<int>(PermissionType::kUnknown) ||
+      permission_type.value() > static_cast<int>(PermissionType::kMaxValue)) {
     return nullptr;
   }
 
@@ -140,7 +142,9 @@
     permission_value = value.value();
   } else {
     absl::optional<int> tri_state = dict.FindInt(kValueKey);
-    if (tri_state.has_value()) {
+    if (tri_state.has_value() &&
+        tri_state.value() >= static_cast<int>(TriState::kAllow) &&
+        tri_state.value() <= static_cast<int>(TriState::kMaxValue)) {
       permission_value = static_cast<TriState>(tri_state.value());
     } else {
       return nullptr;
diff --git a/components/services/app_service/public/cpp/permission_unittest.cc b/components/services/app_service/public/cpp/permission_unittest.cc
index 787f4d0..3e5e942 100644
--- a/components/services/app_service/public/cpp/permission_unittest.cc
+++ b/components/services/app_service/public/cpp/permission_unittest.cc
@@ -7,7 +7,6 @@
 #include <memory>
 #include <utility>
 
-#include "base/logging.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace apps {
diff --git a/components/services/app_service/public/cpp/run_on_os_login_types.cc b/components/services/app_service/public/cpp/run_on_os_login_types.cc
index 359a039..b3ab893 100644
--- a/components/services/app_service/public/cpp/run_on_os_login_types.cc
+++ b/components/services/app_service/public/cpp/run_on_os_login_types.cc
@@ -6,6 +6,13 @@
 
 namespace apps {
 
+namespace {
+
+const char kLoginModeKey[] = "login_mode";
+const char kIsManagedKey[] = "is_managed";
+
+}  // namespace
+
 APP_ENUM_TO_STRING(RunOnOsLoginMode, kUnknown, kNotRun, kWindowed)
 
 RunOnOsLogin::RunOnOsLogin() = default;
@@ -23,4 +30,34 @@
   return !(*this == other);
 }
 
+base::Value::Dict ConvertRunOnOsLoginToDict(
+    const RunOnOsLogin& run_on_os_login) {
+  base::Value::Dict dict;
+  dict.Set(kLoginModeKey, static_cast<int>(run_on_os_login.login_mode));
+  dict.Set(kIsManagedKey, run_on_os_login.is_managed);
+  return dict;
+}
+
+absl::optional<RunOnOsLogin> ConvertDictToRunOnOsLogin(
+    const base::Value::Dict* dict) {
+  if (!dict) {
+    return absl::nullopt;
+  }
+
+  absl::optional<int> login_mode = dict->FindInt(kLoginModeKey);
+  if (!login_mode.has_value() ||
+      login_mode.value() < static_cast<int>(RunOnOsLoginMode::kUnknown) ||
+      login_mode.value() > static_cast<int>(RunOnOsLoginMode::kMaxValue)) {
+    return absl::nullopt;
+  }
+
+  absl::optional<bool> is_managed = dict->FindBool(kIsManagedKey);
+  if (!is_managed.has_value()) {
+    return absl::nullopt;
+  }
+
+  return RunOnOsLogin(static_cast<RunOnOsLoginMode>(login_mode.value()),
+                      is_managed.value());
+}
+
 }  // namespace apps
\ No newline at end of file
diff --git a/components/services/app_service/public/cpp/run_on_os_login_types.h b/components/services/app_service/public/cpp/run_on_os_login_types.h
index 375d86e..2a90914 100644
--- a/components/services/app_service/public/cpp/run_on_os_login_types.h
+++ b/components/services/app_service/public/cpp/run_on_os_login_types.h
@@ -10,18 +10,18 @@
 #include <vector>
 
 #include "base/component_export.h"
+#include "base/values.h"
 #include "components/services/app_service/public/cpp/macros.h"
 
 namespace apps {
 
-ENUM_FOR_COMPONENT(APP_TYPES,
-                   RunOnOsLoginMode,
-                   // kUnknown to be used for app_update.cc.
-                   kUnknown,
-                   // App won't run on OS Login.
-                   kNotRun,
-                   // App runs in windowed mode on OS Login.
-                   kWindowed)
+ENUM(RunOnOsLoginMode,
+     // kUnknown to be used for app_update.cc.
+     kUnknown,
+     // App won't run on OS Login.
+     kNotRun,
+     // App runs in windowed mode on OS Login.
+     kWindowed)
 
 struct COMPONENT_EXPORT(APP_TYPES) RunOnOsLogin {
   RunOnOsLogin();
@@ -48,6 +48,20 @@
 
 using RunOnOsLoginPtr = std::unique_ptr<RunOnOsLogin>;
 
+// Converts `run_on_os_login` to base::Value::Dict, e.g.:
+// {
+//   "login_mode": 2,
+//   "is_managed": false,
+// }
+COMPONENT_EXPORT(APP_TYPES)
+base::Value::Dict ConvertRunOnOsLoginToDict(
+    const RunOnOsLogin& run_on_os_login);
+
+// Converts base::Value::Dict to RunOnOsLoginPtr.
+COMPONENT_EXPORT(APP_TYPES)
+absl::optional<RunOnOsLogin> ConvertDictToRunOnOsLogin(
+    const base::Value::Dict* dict);
+
 }  // namespace apps
 
 #endif  // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_RUN_ON_OS_LOGIN_TYPES_H_
diff --git a/components/services/app_service/public/cpp/run_on_os_login_types_unittest.cc b/components/services/app_service/public/cpp/run_on_os_login_types_unittest.cc
new file mode 100644
index 0000000..238186f
--- /dev/null
+++ b/components/services/app_service/public/cpp/run_on_os_login_types_unittest.cc
@@ -0,0 +1,34 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/app_service/public/cpp/run_on_os_login_types.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace apps {
+
+using RunOnOsLoginTest = testing::Test;
+
+TEST_F(RunOnOsLoginTest, VerifyRunOnOsLoginConvert) {
+  {
+    // Verify the convert function can work for null permission.
+    EXPECT_FALSE(ConvertDictToRunOnOsLogin(nullptr).has_value());
+  }
+
+  {
+    RunOnOsLogin run_on_os_login(RunOnOsLoginMode::kNotRun,
+                                 /*is_managed=*/true);
+    auto dict = ConvertRunOnOsLoginToDict(run_on_os_login);
+    EXPECT_EQ(run_on_os_login, ConvertDictToRunOnOsLogin(&dict).value());
+  }
+
+  {
+    RunOnOsLogin run_on_os_login(RunOnOsLoginMode::kWindowed,
+                                 /*is_managed=*/false);
+    auto dict = ConvertRunOnOsLoginToDict(run_on_os_login);
+    EXPECT_EQ(run_on_os_login, ConvertDictToRunOnOsLogin(&dict).value());
+  }
+}
+
+}  // namespace apps
diff --git a/components/services/quarantine/BUILD.gn b/components/services/quarantine/BUILD.gn
index 55ae194..1697d906 100644
--- a/components/services/quarantine/BUILD.gn
+++ b/components/services/quarantine/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 
 if (is_android) {
   import("//build/config/android/rules.gni")
diff --git a/components/services/screen_ai/buildflags/features.gni b/components/services/screen_ai/buildflags/features.gni
index 8a36884..2a9746d 100644
--- a/components/services/screen_ai/buildflags/features.gni
+++ b/components/services/screen_ai/buildflags/features.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 
 declare_args() {
diff --git a/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.cc b/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.cc
index 7797f9d..488ae576 100644
--- a/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.cc
+++ b/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.cc
@@ -359,11 +359,6 @@
 
 }  // namespace
 
-FakeLevelDBFactory::FakeLevelDBFactory(leveldb_env::Options database_options,
-                                       const std::string& in_memory_db_name)
-    : DefaultLevelDBFactory(database_options, in_memory_db_name) {}
-FakeLevelDBFactory::~FakeLevelDBFactory() {}
-
 // static
 std::unique_ptr<leveldb::DB> FakeLevelDBFactory::CreateFlakyDB(
     std::unique_ptr<leveldb::DB> db,
@@ -391,47 +386,4 @@
       std::make_unique<BrokenDB>(error_to_return), reported_file_path);
 }
 
-void FakeLevelDBFactory::EnqueueNextOpenDBResult(
-    std::unique_ptr<leveldb::DB> db,
-    leveldb::Status status) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  next_dbs_.push(std::make_tuple(std::move(db), status));
-}
-
-std::tuple<std::unique_ptr<leveldb::DB>, leveldb::Status>
-FakeLevelDBFactory::OpenDB(const std::string& name,
-                           bool create_if_missing,
-                           size_t write_buffer_size) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (next_dbs_.empty())
-    return DefaultLevelDBFactory::OpenDB(name, create_if_missing,
-                                         write_buffer_size);
-  auto tuple = std::move(next_dbs_.front());
-  next_dbs_.pop();
-  return tuple;
-}
-
-void FakeLevelDBFactory::EnqueueNextOpenLevelDBStateResult(
-    scoped_refptr<LevelDBState> state,
-    leveldb::Status status,
-    bool is_disk_full) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  next_leveldb_states_.push(
-      std::make_tuple(std::move(state), status, is_disk_full));
-}
-
-std::tuple<scoped_refptr<LevelDBState>, leveldb::Status, bool /*disk_full*/>
-FakeLevelDBFactory::OpenLevelDBState(const base::FilePath& file_name,
-                                     bool create_if_missing,
-                                     size_t write_buffer_size) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (next_leveldb_states_.empty()) {
-    return DefaultLevelDBFactory::OpenLevelDBState(file_name, create_if_missing,
-                                                   write_buffer_size);
-  }
-  auto tuple = std::move(next_leveldb_states_.front());
-  next_leveldb_states_.pop();
-  return tuple;
-}
-
 }  // namespace content
diff --git a/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.h b/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.h
index 1a1efc7..804b782 100644
--- a/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.h
+++ b/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.h
@@ -12,7 +12,6 @@
 #include "base/files/file_path.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/sequence_checker.h"
-#include "components/services/storage/indexed_db/leveldb/leveldb_factory.h"
 #include "third_party/leveldatabase/env_chromium.h"
 #include "third_party/leveldatabase/src/include/leveldb/comparator.h"
 #include "third_party/leveldatabase/src/include/leveldb/db.h"
@@ -21,14 +20,9 @@
 namespace content {
 class LevelDBState;
 
-// Used for unittests, this factory will only create in-memory leveldb
-// databases, and will optionally allow the user to override the next
-// LevelDBState returned with |EnqueueNextLevelDBState|.
-class FakeLevelDBFactory : public DefaultLevelDBFactory {
+class FakeLevelDBFactory {
  public:
-  FakeLevelDBFactory(leveldb_env::Options database_options,
-                     const std::string& in_memory_db_name);
-  ~FakeLevelDBFactory() override;
+  FakeLevelDBFactory() = delete;
 
   struct FlakePoint {
     int calls_before_flake;
@@ -51,33 +45,6 @@
   static std::pair<std::unique_ptr<leveldb::DB>,
                    base::OnceCallback<void(leveldb::Status)>>
   CreateBreakableDB(std::unique_ptr<leveldb::DB> db);
-
-  void EnqueueNextOpenDBResult(std::unique_ptr<leveldb::DB>,
-                               leveldb::Status status);
-
-  std::tuple<std::unique_ptr<leveldb::DB>, leveldb::Status> OpenDB(
-      const std::string& name,
-      bool create_if_missing,
-      size_t write_buffer_size) override;
-
-  void EnqueueNextOpenLevelDBStateResult(scoped_refptr<LevelDBState> state,
-                                         leveldb::Status status,
-                                         bool is_disk_full);
-
-  std::tuple<scoped_refptr<LevelDBState>, leveldb::Status, bool /*disk_full*/>
-  OpenLevelDBState(const base::FilePath& file_name,
-                   bool create_if_missing,
-                   size_t write_buffer_size) override;
-
- private:
-  SEQUENCE_CHECKER(sequence_checker_);
-
-  std::queue<std::tuple<std::unique_ptr<leveldb::DB>, leveldb::Status>>
-      next_dbs_;
-  std::queue<std::tuple<scoped_refptr<LevelDBState>,
-                        leveldb::Status,
-                        bool /*disk_full*/>>
-      next_leveldb_states_;
 };
 
 }  // namespace content
diff --git a/components/services/storage/indexed_db/leveldb/leveldb_factory.cc b/components/services/storage/indexed_db/leveldb/leveldb_factory.cc
index 6cb53c29..e36c411 100644
--- a/components/services/storage/indexed_db/leveldb/leveldb_factory.cc
+++ b/components/services/storage/indexed_db/leveldb/leveldb_factory.cc
@@ -12,14 +12,13 @@
 
 namespace content {
 
-DefaultLevelDBFactory::DefaultLevelDBFactory(
-    leveldb_env::Options database_options,
-    const std::string& in_memory_db_name)
+LevelDBFactory::LevelDBFactory(leveldb_env::Options database_options,
+                               const std::string& in_memory_db_name)
     : options_(database_options), in_memory_db_name_(in_memory_db_name) {}
-DefaultLevelDBFactory::~DefaultLevelDBFactory() = default;
+LevelDBFactory::~LevelDBFactory() = default;
 
 std::tuple<std::unique_ptr<leveldb::DB>, leveldb::Status>
-DefaultLevelDBFactory::OpenInMemoryDB(leveldb::Env* in_memory_env) {
+LevelDBFactory::OpenInMemoryDB(leveldb::Env* in_memory_env) {
   constexpr int64_t kBytesInOneMegabyte = 1024 * 1024;
   leveldb_env::Options in_memory_options = options_;
   in_memory_options.write_buffer_size =
@@ -34,9 +33,9 @@
 }
 
 std::tuple<std::unique_ptr<leveldb::DB>, leveldb::Status>
-DefaultLevelDBFactory::OpenDB(const std::string& name,
-                              bool create_if_missing,
-                              size_t write_buffer_size) {
+LevelDBFactory::OpenDB(const std::string& name,
+                       bool create_if_missing,
+                       size_t write_buffer_size) {
   std::unique_ptr<leveldb::DB> db;
   options_.create_if_missing = create_if_missing;
   options_.write_buffer_size = write_buffer_size;
@@ -47,9 +46,9 @@
 std::tuple<scoped_refptr<LevelDBState>,
            leveldb::Status,
            /* is_disk_full= */ bool>
-DefaultLevelDBFactory::OpenLevelDBState(const base::FilePath& file_name,
-                                        bool create_if_missing,
-                                        size_t write_buffer_size) {
+LevelDBFactory::OpenLevelDBState(const base::FilePath& file_name,
+                                 bool create_if_missing,
+                                 size_t write_buffer_size) {
   if (file_name.empty()) {
     if (!create_if_missing)
       return {nullptr, leveldb::Status::NotFound("", ""), false};
@@ -95,8 +94,7 @@
           status, false};
 }
 
-leveldb::Status DefaultLevelDBFactory::DestroyLevelDB(
-    const base::FilePath& path) {
+leveldb::Status LevelDBFactory::DestroyLevelDB(const base::FilePath& path) {
   return leveldb::DestroyDB(path.AsUTF8Unsafe(), options_);
 }
 
diff --git a/components/services/storage/indexed_db/leveldb/leveldb_factory.h b/components/services/storage/indexed_db/leveldb/leveldb_factory.h
index e87c976..ca851fa 100644
--- a/components/services/storage/indexed_db/leveldb/leveldb_factory.h
+++ b/components/services/storage/indexed_db/leveldb/leveldb_factory.h
@@ -20,71 +20,48 @@
 namespace content {
 class LevelDBState;
 
-// Factory class used to open leveldb databases, and stores all necessary
-// objects in a LevelDBState. This interface exists so that it can be mocked out
-// for tests.
+// Factory class used to open and close leveldb databases. This is left over
+// from a time when it was mocked out for tests and should probably be removed.
 class LevelDBFactory {
  public:
-  virtual ~LevelDBFactory() = default;
-
-  // Creates an in-memory database.
-  virtual std::tuple<std::unique_ptr<leveldb::DB>, leveldb::Status>
-  OpenInMemoryDB(leveldb::Env* in_memory_env) = 0;
-
-  // Opens a leveldb database with the given name. If |create_if_missing| is
-  // true, then the database will be created if it does not exist.
-  virtual std::tuple<std::unique_ptr<leveldb::DB>, leveldb::Status> OpenDB(
-      const std::string& name,
-      bool create_if_missing,
-      size_t write_buffer_size) = 0;
-
-  // Opens a leveldb database and returns it inside of a LevelDBState. If the
-  // |file_name| is empty, then the database will be in-memory. If
-  // |create_if_missing| is false and the database doesn't exist, then the
-  // return tuple will be {nullptr, leveldb::Status::NotFound("", ""), false}.
-  virtual std::tuple<scoped_refptr<LevelDBState>,
-                     leveldb::Status,
-                     /* is_disk_full= */ bool>
-  OpenLevelDBState(const base::FilePath& file_name,
-                   bool create_if_missing,
-                   size_t write_buffer_size) = 0;
-
-  // Assumes that there is no leveldb database currently running for this path.
-  virtual leveldb::Status DestroyLevelDB(const base::FilePath& path) = 0;
-};
-
-class DefaultLevelDBFactory : public LevelDBFactory {
- public:
   // The |database_options| are used to open any database. The
   // |create_if_missing| is supplied by Open*() calls, and |write_buffer_size|
   // is calculated during the Open* calls as well. |in_memory_db_name| is used
   // for memory profiling reporting in the in-memory database environment.
-  DefaultLevelDBFactory(leveldb_env::Options database_options,
-                        const std::string& in_memory_db_name);
+  LevelDBFactory(leveldb_env::Options database_options,
+                 const std::string& in_memory_db_name);
 
-  DefaultLevelDBFactory(const DefaultLevelDBFactory&) = delete;
-  DefaultLevelDBFactory& operator=(const DefaultLevelDBFactory&) = delete;
+  LevelDBFactory(const LevelDBFactory&) = delete;
+  LevelDBFactory& operator=(const LevelDBFactory&) = delete;
 
-  ~DefaultLevelDBFactory() override;
+  ~LevelDBFactory();
 
+  // Creates an in-memory database.
   std::tuple<std::unique_ptr<leveldb::DB>, leveldb::Status> OpenInMemoryDB(
-      leveldb::Env* in_memory_env) override;
+      leveldb::Env* in_memory_env);
 
+  // Opens a leveldb database with the given name. If |create_if_missing| is
+  // true, then the database will be created if it does not exist.
   std::tuple<std::unique_ptr<leveldb::DB>, leveldb::Status> OpenDB(
       const std::string& name,
       bool create_if_missing,
-      size_t write_buffer_size) override;
+      size_t write_buffer_size);
 
+  // Opens a leveldb database and returns it inside of a LevelDBState. If the
+  // |file_name| is empty, then the database will be in-memory. If
+  // |create_if_missing| is false and the database doesn't exist, then the
+  // return tuple will be {nullptr, leveldb::Status::NotFound("", ""), false}.
   std::tuple<scoped_refptr<LevelDBState>,
              leveldb::Status,
              /* is_disk_full= */ bool>
   OpenLevelDBState(const base::FilePath& file_name,
                    bool create_if_missing,
-                   size_t write_buffer_size) override;
+                   size_t write_buffer_size);
 
-  leveldb::Status DestroyLevelDB(const base::FilePath& path) override;
+  // Assumes that there is no leveldb database currently running for this path.
+  leveldb::Status DestroyLevelDB(const base::FilePath& path);
 
- protected:
+ private:
   leveldb_env::Options options_;
   std::string in_memory_db_name_;
 };
diff --git a/components/services/storage/indexed_db/scopes/leveldb_scopes_test_utils.cc b/components/services/storage/indexed_db/scopes/leveldb_scopes_test_utils.cc
index 860bdb3a..a2f01d2 100644
--- a/components/services/storage/indexed_db/scopes/leveldb_scopes_test_utils.cc
+++ b/components/services/storage/indexed_db/scopes/leveldb_scopes_test_utils.cc
@@ -45,9 +45,10 @@
 
 void LevelDBScopesTestBase::SetUp() {
   large_string_.assign(kWriteBatchSizeForTesting + 1, 'e');
-  if (!leveldb_factory_)
-    leveldb_factory_ = std::make_unique<FakeLevelDBFactory>(GetLevelDBOptions(),
-                                                            "scopes-test-db");
+  if (!leveldb_factory_) {
+    leveldb_factory_ =
+        std::make_unique<LevelDBFactory>(GetLevelDBOptions(), "scopes-test-db");
+  }
 }
 
 void LevelDBScopesTestBase::TearDown() {
@@ -95,25 +96,29 @@
 }
 
 void LevelDBScopesTestBase::SetUpBreakableDB(
-    base::OnceCallback<void(leveldb::Status)>* callback) {
+    base::OnceCallback<void(leveldb::Status)>* break_db) {
   if (leveldb_)
     TearDown();
   ASSERT_TRUE(temp_directory_.CreateUniqueTempDir());
 
-  auto [temp_real_db, status] =
-      leveldb_factory_->OpenDB(temp_directory_.GetPath().AsUTF8Unsafe(),
-                               /*create_if_missing=*/true, kWriteBufferSize);
+  auto options = GetLevelDBOptions();
+  std::unique_ptr<leveldb::DB> real_db;
+  options.create_if_missing = true;
+  options.write_buffer_size = kWriteBufferSize;
+  leveldb::Status status = leveldb_env::OpenDB(
+      options, temp_directory_.GetPath().AsUTF8Unsafe(), &real_db);
+
   ASSERT_TRUE(status.ok());
-  ASSERT_TRUE(temp_real_db);
+  ASSERT_TRUE(real_db);
 
   std::unique_ptr<leveldb::DB> breakable_db;
-  std::tie(breakable_db, *callback) =
-      FakeLevelDBFactory::CreateBreakableDB(std::move(temp_real_db));
+  std::tie(breakable_db, *break_db) =
+      FakeLevelDBFactory::CreateBreakableDB(std::move(real_db));
   ASSERT_TRUE(breakable_db);
 
-  leveldb_factory_->EnqueueNextOpenDBResult(std::move(breakable_db),
-                                            leveldb::Status::OK());
-  CreateAndSaveLevelDBState();
+  leveldb_ =
+      LevelDBState::CreateForDiskDB(options.comparator, std::move(breakable_db),
+                                    std::move(temp_directory_.GetPath()));
 }
 
 void LevelDBScopesTestBase::SetUpFlakyDB(
@@ -122,18 +127,23 @@
     TearDown();
   ASSERT_TRUE(temp_directory_.CreateUniqueTempDir());
 
-  auto [temp_db, status] =
-      leveldb_factory_->OpenDB(temp_directory_.GetPath().AsUTF8Unsafe(),
-                               /*create_if_missing=*/true, kWriteBufferSize);
+  auto options = GetLevelDBOptions();
+  std::unique_ptr<leveldb::DB> real_db;
+  options.create_if_missing = true;
+  options.write_buffer_size = kWriteBufferSize;
+  leveldb::Status status = leveldb_env::OpenDB(
+      options, temp_directory_.GetPath().AsUTF8Unsafe(), &real_db);
+
   ASSERT_TRUE(status.ok());
-  ASSERT_TRUE(temp_db);
+  ASSERT_TRUE(real_db);
 
   std::unique_ptr<leveldb::DB> flaky_db = FakeLevelDBFactory::CreateFlakyDB(
-      std::move(temp_db), std::move(flake_points));
+      std::move(real_db), std::move(flake_points));
+  ASSERT_TRUE(flaky_db);
 
-  leveldb_factory_->EnqueueNextOpenDBResult(std::move(flaky_db),
-                                            leveldb::Status::OK());
-  CreateAndSaveLevelDBState();
+  leveldb_ =
+      LevelDBState::CreateForDiskDB(options.comparator, std::move(flaky_db),
+                                    std::move(temp_directory_.GetPath()));
 }
 
 void LevelDBScopesTestBase::WriteScopesMetadata(int64_t scope_number,
diff --git a/components/services/storage/indexed_db/scopes/leveldb_scopes_test_utils.h b/components/services/storage/indexed_db/scopes/leveldb_scopes_test_utils.h
index 6119cdc..0d27c2c 100644
--- a/components/services/storage/indexed_db/scopes/leveldb_scopes_test_utils.h
+++ b/components/services/storage/indexed_db/scopes/leveldb_scopes_test_utils.h
@@ -10,6 +10,7 @@
 #include "base/test/task_environment.h"
 #include "base/threading/thread_restrictions.h"
 #include "components/services/storage/indexed_db/leveldb/fake_leveldb_factory.h"
+#include "components/services/storage/indexed_db/leveldb/leveldb_factory.h"
 #include "components/services/storage/indexed_db/leveldb/leveldb_state.h"
 #include "components/services/storage/indexed_db/locks/partitioned_lock_manager.h"
 #include "components/services/storage/indexed_db/scopes/leveldb_scopes_coding.h"
@@ -111,7 +112,7 @@
   const std::vector<uint8_t> metadata_prefix_ = {'a'};
   const std::vector<uint8_t> db_prefix_ = {'b'};
 
-  std::unique_ptr<FakeLevelDBFactory> leveldb_factory_;
+  std::unique_ptr<LevelDBFactory> leveldb_factory_;
   scoped_refptr<LevelDBState> leveldb_;
   std::string large_string_;
   LevelDBScopesUndoTask undo_task_buffer_;
diff --git a/components/signin/internal/identity_manager/account_tracker_service.cc b/components/signin/internal/identity_manager/account_tracker_service.cc
index 4a9b0aa..a4b53c07 100644
--- a/components/signin/internal/identity_manager/account_tracker_service.cc
+++ b/components/signin/internal/identity_manager/account_tracker_service.cc
@@ -891,7 +891,7 @@
 
 void AccountTrackerService::SeedAccountsInfo(
     const std::vector<CoreAccountInfo>& core_account_infos,
-    const CoreAccountId& primary_account_id) {
+    const absl::optional<CoreAccountId>& primary_account_id) {
   DVLOG(1) << "AccountTrackerService.SeedAccountsInfo: "
            << " number of accounts " << core_account_infos.size();
 
diff --git a/components/signin/internal/identity_manager/account_tracker_service.h b/components/signin/internal/identity_manager/account_tracker_service.h
index 894f9068..8bb2674 100644
--- a/components/signin/internal/identity_manager/account_tracker_service.h
+++ b/components/signin/internal/identity_manager/account_tracker_service.h
@@ -115,8 +115,9 @@
 
   // Seeds the accounts with |core_account_infos|. The primary account id is
   // passed to keep it from getting removed.
-  void SeedAccountsInfo(const std::vector<CoreAccountInfo>& core_account_infos,
-                        const CoreAccountId& primary_account_id);
+  void SeedAccountsInfo(
+      const std::vector<CoreAccountInfo>& core_account_infos,
+      const absl::optional<CoreAccountId>& primary_account_id);
 
   // Sets whether the account is a Unicorn account.
   void SetIsChildAccount(const CoreAccountId& account_id,
diff --git a/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc b/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc
index c276fbf..6e552d53 100644
--- a/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc
+++ b/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc
@@ -7,13 +7,14 @@
 #include "base/check.h"
 #include "build/build_config.h"
 #include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+#include "components/signin/public/identity_manager/account_info.h"
 
 namespace signin {
 
 DeviceAccountsSynchronizerImpl::DeviceAccountsSynchronizerImpl(
     ProfileOAuth2TokenServiceDelegate* token_service_delegate)
     : token_service_delegate_(token_service_delegate) {
-  DCHECK(token_service_delegate_);
+  CHECK(token_service_delegate_);
 }
 
 DeviceAccountsSynchronizerImpl::~DeviceAccountsSynchronizerImpl() = default;
@@ -25,6 +26,16 @@
       primary_account_id);
 }
 
+#if BUILDFLAG(IS_ANDROID)
+void DeviceAccountsSynchronizerImpl::
+    SeedAccountsThenReloadAllAccountsWithPrimaryAccount(
+        const std::vector<CoreAccountInfo>& core_account_infos,
+        const absl::optional<CoreAccountId>& primary_account_id) {
+  token_service_delegate_->SeedAccountsThenReloadAllAccountsWithPrimaryAccount(
+      core_account_infos, primary_account_id);
+}
+#endif
+
 #if BUILDFLAG(IS_IOS)
 void DeviceAccountsSynchronizerImpl::ReloadAccountFromSystem(
     const CoreAccountId& account_id) {
diff --git a/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h b/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h
index 6215332..85e4023 100644
--- a/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h
+++ b/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h
@@ -24,6 +24,12 @@
   void ReloadAllAccountsFromSystemWithPrimaryAccount(
       const absl::optional<CoreAccountId>& primary_account_id) override;
 
+#if BUILDFLAG(IS_ANDROID)
+  void SeedAccountsThenReloadAllAccountsWithPrimaryAccount(
+      const std::vector<CoreAccountInfo>& core_account_infos,
+      const absl::optional<CoreAccountId>& primary_account_id) override;
+#endif
+
 #if BUILDFLAG(IS_IOS)
   void ReloadAccountFromSystem(const CoreAccountId& account_id) override;
 #endif
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
index 83b01be..cfed4c8 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
@@ -16,6 +16,7 @@
 #include "base/observer_list.h"
 #include "build/build_config.h"
 #include "components/signin/public/base/signin_buildflags.h"
+#include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/load_credentials_state.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -162,6 +163,11 @@
 #endif
 
 #if BUILDFLAG(IS_ANDROID)
+  // Triggers platform specific implementation to reload accounts from system.
+  virtual void SeedAccountsThenReloadAllAccountsWithPrimaryAccount(
+      const std::vector<CoreAccountInfo>& core_account_infos,
+      const absl::optional<CoreAccountId>& primary_account_id) {}
+
   // Returns a reference to the corresponding Java object.
   virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() = 0;
 #endif
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc
index e424de2..89a6342 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc
@@ -259,19 +259,8 @@
 
 void ProfileOAuth2TokenServiceDelegateAndroid::
     SeedAccountsThenReloadAllAccountsWithPrimaryAccount(
-        JNIEnv* env,
-        const base::android::JavaParamRef<jobjectArray>& j_core_account_infos,
-        const base::android::JavaParamRef<jobject>& j_primary_account_id) {
-  std::vector<CoreAccountInfo> core_account_infos;
-  for (size_t i = 0; i < SafeGetArrayLength(env, j_core_account_infos); i++) {
-    base::android::ScopedJavaLocalRef<jobject> core_account_info_java(
-        env, env->GetObjectArrayElement(j_core_account_infos.obj(), i));
-    core_account_infos.push_back(
-        ConvertFromJavaCoreAccountInfo(env, core_account_info_java));
-  }
-
-  CoreAccountId primary_account_id =
-      ConvertFromJavaCoreAccountId(env, j_primary_account_id);
+        const std::vector<CoreAccountInfo>& core_account_infos,
+        const absl::optional<CoreAccountId>& primary_account_id) {
   account_tracker_service_->SeedAccountsInfo(core_account_infos,
                                              primary_account_id);
   std::vector<CoreAccountId> account_ids;
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.h b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.h
index e8a8a2a..3302785 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.h
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.h
@@ -60,9 +60,8 @@
   // Seeds the accounts with |core_account_infos| then resumes the reload of
   // accounts once the account seeding is complete.
   void SeedAccountsThenReloadAllAccountsWithPrimaryAccount(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jobjectArray>& j_core_account_infos,
-      const base::android::JavaParamRef<jobject>& j_primary_account_id);
+      const std::vector<CoreAccountInfo>& core_account_infos,
+      const absl::optional<CoreAccountId>& primary_account_id) override;
 
   // Resumes the reload of accounts once the account seeding is complete.
   // TODO(crbug.com/934688) Once ProfileOAuth2TokenServiceDelegate.java is
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoService.java b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoService.java
index a5d1838..84bb06b 100644
--- a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoService.java
+++ b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoService.java
@@ -22,7 +22,8 @@
     }
 
     /**
-     * Gets the {@link AccountInfo} of the given account email.
+     * Gets the {@link AccountInfo} of the given account email. TODO(crbug/1491005): Replace all
+     * calls to this method by calls to IdentityManager.findExtendedAccountInfoByEmailAddress().
      */
     Promise<AccountInfo> getAccountInfoByEmail(String email);
 
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoServiceImpl.java b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoServiceImpl.java
index 57934dd..d0dc5c9 100644
--- a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoServiceImpl.java
+++ b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoServiceImpl.java
@@ -6,6 +6,8 @@
 
 import org.chromium.base.ObserverList;
 import org.chromium.base.Promise;
+import org.chromium.components.signin.SigninFeatureMap;
+import org.chromium.components.signin.SigninFeatures;
 import org.chromium.components.signin.base.AccountInfo;
 import org.chromium.components.signin.base.CoreAccountInfo;
 
@@ -34,11 +36,16 @@
     @Override
     public Promise<AccountInfo> getAccountInfoByEmail(String email) {
         final Promise<AccountInfo> accountInfoPromise = new Promise<>();
-        mAccountTrackerService.legacySeedAccountsIfNeeded(
-                () -> {
-                    accountInfoPromise.fulfill(
-                            mIdentityManager.findExtendedAccountInfoByEmailAddress(email));
-                });
+        if (SigninFeatureMap.isEnabled(SigninFeatures.SEED_ACCOUNTS_REVAMP)) {
+            accountInfoPromise.fulfill(
+                    mIdentityManager.findExtendedAccountInfoByEmailAddress(email));
+        } else {
+            mAccountTrackerService.legacySeedAccountsIfNeeded(
+                    () -> {
+                        accountInfoPromise.fulfill(
+                                mIdentityManager.findExtendedAccountInfoByEmailAddress(email));
+                    });
+        }
         return accountInfoPromise;
     }
 
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityMutator.java b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityMutator.java
index 1bfecc7..13ae7dc 100644
--- a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityMutator.java
+++ b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityMutator.java
@@ -10,10 +10,13 @@
 import org.jni_zero.NativeMethods;
 
 import org.chromium.components.signin.base.CoreAccountId;
+import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 import org.chromium.components.signin.metrics.SignoutDelete;
 import org.chromium.components.signin.metrics.SignoutReason;
 
+import java.util.List;
+
 /**
  * IdentityMutator is the write interface of IdentityManager, see identity_mutator.h for more
  * information.
@@ -78,16 +81,33 @@
                 mNativeIdentityMutator, accountId);
     }
 
+    public void seedAccountsThenReloadAllAccountsWithPrimaryAccount(
+            List<CoreAccountInfo> coreAccountInfos, @Nullable CoreAccountId primaryAccountId) {
+        IdentityMutatorJni.get()
+                .seedAccountsThenReloadAllAccountsWithPrimaryAccount(
+                        mNativeIdentityMutator,
+                        coreAccountInfos.toArray(new CoreAccountInfo[0]),
+                        primaryAccountId);
+    }
+
     @NativeMethods
     interface Natives {
         public @PrimaryAccountError int setPrimaryAccount(long nativeJniIdentityMutator,
                 CoreAccountId accountId, @ConsentLevel int consentLevel,
                 @SigninAccessPoint int accessPoint);
+
         public boolean clearPrimaryAccount(long nativeJniIdentityMutator,
                 @SignoutReason int sourceMetric, @SignoutDelete int deleteMetric);
+
         public void revokeSyncConsent(long nativeJniIdentityMutator,
                 @SignoutReason int sourceMetric, @SignoutDelete int deleteMetric);
+
         public void reloadAllAccountsFromSystemWithPrimaryAccount(
                 long nativeJniIdentityMutator, @Nullable CoreAccountId accountId);
+
+        public void seedAccountsThenReloadAllAccountsWithPrimaryAccount(
+                long nativeJniIdentityMutator,
+                CoreAccountInfo[] coreAccountInfos,
+                @Nullable CoreAccountId primaryAccountId);
     }
 }
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegate.java b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegate.java
index d45643f..3df61ca 100644
--- a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegate.java
+++ b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegate.java
@@ -22,7 +22,6 @@
 import org.chromium.components.signin.ConnectionRetry.AuthTask;
 import org.chromium.components.signin.SigninFeatureMap;
 import org.chromium.components.signin.SigninFeatures;
-import org.chromium.components.signin.base.CoreAccountId;
 import org.chromium.components.signin.base.CoreAccountInfo;
 
 import java.util.List;
@@ -194,23 +193,6 @@
                 });
     }
 
-    @VisibleForTesting
-    // TODO(crbug/1491005): Implement the native call to this method and then remove if from the
-    // Java layer.
-    void seedAndReloadAccountsWithPrimaryAccount(
-            List<CoreAccountInfo> coreAccountInfos, @Nullable CoreAccountId primaryAccountId) {
-        ThreadUtils.assertOnUiThread();
-        if (!SigninFeatureMap.isEnabled(SigninFeatures.SEED_ACCOUNTS_REVAMP)) {
-            throw new IllegalStateException(
-                    "This method should never be called when SeedAccountsRevamp is disabled");
-        }
-        ProfileOAuth2TokenServiceDelegateJni.get()
-                .seedAccountsThenReloadAllAccountsWithPrimaryAccount(
-                        mNativeProfileOAuth2TokenServiceDelegate,
-                        coreAccountInfos.toArray(new CoreAccountInfo[0]),
-                        primaryAccountId);
-    }
-
     @NativeMethods
     interface Natives {
         /**
@@ -230,10 +212,5 @@
                 long nativeProfileOAuth2TokenServiceDelegateAndroid,
                 @Nullable String accountId,
                 String[] deviceAccountEmails);
-
-        void seedAccountsThenReloadAllAccountsWithPrimaryAccount(
-                long nativeProfileOAuth2TokenServiceDelegateAndroid,
-                CoreAccountInfo[] coreAccountInfos,
-                @Nullable CoreAccountId primaryAccountId);
     }
 }
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegateTest.java b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegateTest.java
index 1e1f183..bcdf1665f 100644
--- a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegateTest.java
+++ b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegateTest.java
@@ -198,21 +198,4 @@
                 .reloadAllAccountsWithPrimaryAccountAfterSeeding(
                         NATIVE_DELEGATE, null, new String[] {ACCOUNT.name});
     }
-
-    @Test
-    @SmallTest
-    @Features.EnableFeatures(SigninFeatures.SEED_ACCOUNTS_REVAMP)
-    public void testSeedAndReloadAccountsWhenAccountsAreSeeded_seedAccountRevampEnabled() {
-        mAccountManagerFacade.addAccount(ACCOUNT);
-        ThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    mDelegate.seedAndReloadAccountsWithPrimaryAccount(
-                            List.of(CORE_ACCOUNT_INFO), CORE_ACCOUNT_INFO.getId());
-                });
-        verify(mNativeMock)
-                .seedAccountsThenReloadAllAccountsWithPrimaryAccount(
-                        NATIVE_DELEGATE,
-                        new CoreAccountInfo[] {CORE_ACCOUNT_INFO},
-                        CORE_ACCOUNT_INFO.getId());
-    }
 }
diff --git a/components/signin/public/identity_manager/device_accounts_synchronizer.h b/components/signin/public/identity_manager/device_accounts_synchronizer.h
index e98fbe3..5555fa7b 100644
--- a/components/signin/public/identity_manager/device_accounts_synchronizer.h
+++ b/components/signin/public/identity_manager/device_accounts_synchronizer.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_DEVICE_ACCOUNTS_SYNCHRONIZER_H_
 
 #include "build/build_config.h"
+#include "components/signin/public/identity_manager/account_info.h"
 #include "google_apis/gaia/core_account_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -24,6 +25,15 @@
   virtual void ReloadAllAccountsFromSystemWithPrimaryAccount(
       const absl::optional<CoreAccountId>& primary_account_id) = 0;
 
+#if BUILDFLAG(IS_ANDROID)
+  // Reloads the information of all device-level accounts. All device-level
+  // accounts will be visible in IdentityManager::GetAccountsWithRefreshTokens()
+  // with any persistent errors cleared after this method is called.
+  virtual void SeedAccountsThenReloadAllAccountsWithPrimaryAccount(
+      const std::vector<CoreAccountInfo>& core_account_infos,
+      const absl::optional<CoreAccountId>& primary_account_id) = 0;
+#endif
+
 #if BUILDFLAG(IS_IOS)
   // Reloads the information of the device-level account with |account_id|. The
   // account will be visible in IdentityManager::GetAccountsWithRefreshTokens()
diff --git a/components/signin/public/identity_manager/identity_mutator.cc b/components/signin/public/identity_manager/identity_mutator.cc
index 663df8af..262c320 100644
--- a/components/signin/public/identity_manager/identity_mutator.cc
+++ b/components/signin/public/identity_manager/identity_mutator.cc
@@ -12,6 +12,7 @@
 #include "components/signin/public/identity_manager/primary_account_mutator.h"
 
 #if BUILDFLAG(IS_ANDROID)
+#include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
 #include "components/signin/public/android/jni_headers/IdentityMutator_jni.h"
 #include "components/signin/public/identity_manager/account_info.h"
@@ -76,6 +77,29 @@
   device_accounts_synchronizer->ReloadAllAccountsFromSystemWithPrimaryAccount(
       primary_account_id);
 }
+
+void JniIdentityMutator::SeedAccountsThenReloadAllAccountsWithPrimaryAccount(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobjectArray>& j_core_account_infos,
+    const base::android::JavaParamRef<jobject>& j_primary_account_id) {
+  std::vector<CoreAccountInfo> core_account_infos;
+  for (size_t i = 0; i < SafeGetArrayLength(env, j_core_account_infos); i++) {
+    base::android::ScopedJavaLocalRef<jobject> core_account_info_java(
+        env, env->GetObjectArrayElement(j_core_account_infos.obj(), i));
+    core_account_infos.push_back(
+        ConvertFromJavaCoreAccountInfo(env, core_account_info_java));
+  }
+
+  CoreAccountId primary_account_id =
+      ConvertFromJavaCoreAccountId(env, j_primary_account_id);
+
+  DeviceAccountsSynchronizer* device_accounts_synchronizer =
+      identity_mutator_->GetDeviceAccountsSynchronizer();
+  CHECK(device_accounts_synchronizer);
+  device_accounts_synchronizer
+      ->SeedAccountsThenReloadAllAccountsWithPrimaryAccount(core_account_infos,
+                                                            primary_account_id);
+}
 #endif  // BUILDFLAG(IS_ANDROID)
 
 IdentityMutator::IdentityMutator(
diff --git a/components/signin/public/identity_manager/identity_mutator.h b/components/signin/public/identity_manager/identity_mutator.h
index 5f4cfaa4..85876b6 100644
--- a/components/signin/public/identity_manager/identity_mutator.h
+++ b/components/signin/public/identity_manager/identity_mutator.h
@@ -63,6 +63,11 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& primary_account_id);
 
+  void SeedAccountsThenReloadAllAccountsWithPrimaryAccount(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobjectArray>& j_core_account_infos,
+      const base::android::JavaParamRef<jobject>& j_primary_account_id);
+
  private:
   friend IdentityMutator;
 
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn
index a4cbdb40..4546d2e5 100644
--- a/components/variations/BUILD.gn
+++ b/components/variations/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//testing/test.gni")
diff --git a/components/viz/common/resources/shared_image_format.h b/components/viz/common/resources/shared_image_format.h
index 9dc30f46..6d97e85 100644
--- a/components/viz/common/resources/shared_image_format.h
+++ b/components/viz/common/resources/shared_image_format.h
@@ -346,10 +346,6 @@
     SharedImageFormat::MultiPlane(SharedImageFormat::PlaneConfig::kY_U_V,
                                   SharedImageFormat::Subsampling::k420,
                                   SharedImageFormat::ChannelFormat::k8);
-
-// All known multiplanar formats.
-static constexpr SharedImageFormat kAll[5] = {kYV12, kNV12, kNV12A, kP010,
-                                              kI420};
 }  // namespace MultiPlaneFormat
 
 }  // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_surface_dependency.h b/components/viz/service/display_embedder/skia_output_surface_dependency.h
index a515ceb..fa4992262 100644
--- a/components/viz/service/display_embedder/skia_output_surface_dependency.h
+++ b/components/viz/service/display_embedder/skia_output_surface_dependency.h
@@ -103,7 +103,6 @@
   virtual void DidLoseContext(gpu::error::ContextLostReason reason,
                               const GURL& active_url) = 0;
 
-  virtual base::TimeDelta GetGpuBlockedTimeSinceLastSwap() = 0;
   virtual bool NeedsSupportForExternalStencil() = 0;
 
   // This returns true if CompositorGpuThread(aka DrDc thread) is enabled.
diff --git a/components/viz/service/display_embedder/skia_output_surface_dependency_impl.cc b/components/viz/service/display_embedder/skia_output_surface_dependency_impl.cc
index 483ff93..58cec3b 100644
--- a/components/viz/service/display_embedder/skia_output_surface_dependency_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_dependency_impl.cc
@@ -184,11 +184,6 @@
   gpu_service_impl_->DidLoseContext(reason, active_url);
 }
 
-base::TimeDelta
-SkiaOutputSurfaceDependencyImpl::GetGpuBlockedTimeSinceLastSwap() {
-  return gpu_service_impl_->GetGpuScheduler()->TakeTotalBlockingTime();
-}
-
 bool SkiaOutputSurfaceDependencyImpl::NeedsSupportForExternalStencil() {
   return false;
 }
diff --git a/components/viz/service/display_embedder/skia_output_surface_dependency_impl.h b/components/viz/service/display_embedder/skia_output_surface_dependency_impl.h
index 92a1ca4..2b00c4e 100644
--- a/components/viz/service/display_embedder/skia_output_surface_dependency_impl.h
+++ b/components/viz/service/display_embedder/skia_output_surface_dependency_impl.h
@@ -59,7 +59,6 @@
   void DidLoseContext(gpu::error::ContextLostReason reason,
                       const GURL& active_url) override;
 
-  base::TimeDelta GetGpuBlockedTimeSinceLastSwap() override;
   bool NeedsSupportForExternalStencil() override;
   bool IsUsingCompositorGpuThread() override;
 
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 80c4153e..1efe409e 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -2465,10 +2465,6 @@
   return gpu_vsync_callback_;
 }
 
-base::TimeDelta SkiaOutputSurfaceImplOnGpu::GetGpuBlockedTimeSinceLastSwap() {
-  return dependency_->GetGpuBlockedTimeSinceLastSwap();
-}
-
 void SkiaOutputSurfaceImplOnGpu::DidSwapBuffersCompleteInternal(
     gpu::SwapBuffersCompleteParams params,
     const gfx::Size& pixel_size,
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
index 4aa098c..92b11e18 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -241,7 +241,6 @@
   const gpu::gles2::FeatureInfo* GetFeatureInfo() const override;
   const gpu::GpuPreferences& GetGpuPreferences() const override;
   GpuVSyncCallback GetGpuVSyncCallback() override;
-  base::TimeDelta GetGpuBlockedTimeSinceLastSwap() override;
 
   void PostTaskToClientThread(base::OnceClosure closure) {
     dependency_->PostTaskToClientThread(std::move(closure));
diff --git a/components/viz/service/frame_sinks/gmb_video_frame_pool_context_provider_impl.cc b/components/viz/service/frame_sinks/gmb_video_frame_pool_context_provider_impl.cc
index 05720ac9..71c4f91e 100644
--- a/components/viz/service/frame_sinks/gmb_video_frame_pool_context_provider_impl.cc
+++ b/components/viz/service/frame_sinks/gmb_video_frame_pool_context_provider_impl.cc
@@ -102,10 +102,11 @@
                          uint32_t usage,
                          gpu::Mailbox& mailbox,
                          gpu::SyncToken& sync_token) override {
-    mailbox = sii_in_process_->CreateSharedImage(
+    auto client_shared_image = sii_in_process_->CreateSharedImage(
         gpu_memory_buffer, gpu_memory_buffer_manager_, plane, color_space,
         surface_origin, alpha_type, usage, "VizGmbVideoFramePool");
-
+    CHECK(client_shared_image);
+    mailbox = client_shared_image->mailbox();
     sync_token = sii_in_process_->GenVerifiedSyncToken();
   }
 
diff --git a/components/viz/test/test_context_provider.cc b/components/viz/test/test_context_provider.cc
index a8622f6b9..5c31ec0 100644
--- a/components/viz/test/test_context_provider.cc
+++ b/components/viz/test/test_context_provider.cc
@@ -233,7 +233,8 @@
   return base::MakeRefCounted<gpu::ClientSharedImage>(mailbox);
 }
 
-gpu::Mailbox TestSharedImageInterface::CreateSharedImage(
+scoped_refptr<gpu::ClientSharedImage>
+TestSharedImageInterface::CreateSharedImage(
     gfx::GpuMemoryBuffer* gpu_memory_buffer,
     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
     gfx::BufferPlane plane,
@@ -246,7 +247,7 @@
   auto mailbox = gpu::Mailbox::GenerateForSharedImage();
   shared_images_.insert(mailbox);
   most_recent_size_ = gpu_memory_buffer->GetSize();
-  return mailbox;
+  return base::MakeRefCounted<gpu::ClientSharedImage>(mailbox);
 }
 
 void TestSharedImageInterface::UpdateSharedImage(
diff --git a/components/viz/test/test_context_provider.h b/components/viz/test/test_context_provider.h
index 38bcfbe..4a16a42 100644
--- a/components/viz/test/test_context_provider.h
+++ b/components/viz/test/test_context_provider.h
@@ -84,7 +84,7 @@
       base::StringPiece debug_label,
       gfx::GpuMemoryBufferHandle buffer_handle) override;
 
-  gpu::Mailbox CreateSharedImage(
+  scoped_refptr<gpu::ClientSharedImage> CreateSharedImage(
       gfx::GpuMemoryBuffer* gpu_memory_buffer,
       gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
       gfx::BufferPlane plane,
diff --git a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
index 53f280a..74f0843 100644
--- a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
+++ b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
@@ -38,19 +38,68 @@
       WebContentsObserver(web_contents),
       retained_object_set_(base::android::AttachCurrentThread(),
                            retained_object_set),
-      allow_object_contents_inspection_(true) {
+      mojo_enabled_(
+          base::FeatureList::IsEnabled(features::kGinJavaBridgeMojo)) {
   DCHECK(!retained_object_set.is_null());
 }
 
 GinJavaBridgeDispatcherHost::~GinJavaBridgeDispatcherHost() {
 }
 
+void GinJavaBridgeDispatcherHost::BindNewHost(
+    GlobalRenderFrameHostId routing_id,
+    mojo::PendingReceiver<mojom::GinJavaBridgeHost> host) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  JavaBridgeThread::GetTaskRunner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &GinJavaBridgeDispatcherHost::BindNewHostOnBackgroundThread, this,
+          routing_id, std::move(host)));
+}
+
+void GinJavaBridgeDispatcherHost::BindNewHostOnBackgroundThread(
+    GlobalRenderFrameHostId routing_id,
+    mojo::PendingReceiver<mojom::GinJavaBridgeHost> host) {
+  DCHECK(JavaBridgeThread::CurrentlyOn());
+  receivers_.Add(this, std::move(host), routing_id);
+}
+
+void GinJavaBridgeDispatcherHost::ClearAllReceivers() {
+  DCHECK(JavaBridgeThread::CurrentlyOn());
+  receivers_.set_disconnect_handler({});
+  receivers_.Clear();
+  object_receivers_.set_disconnect_handler({});
+  object_receivers_.Clear();
+}
+
+mojom::GinJavaBridge* GinJavaBridgeDispatcherHost::GetJavaBridge(
+    RenderFrameHost* frame_host,
+    bool should_create) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  CHECK(mojo_enabled_);
+
+  auto routing_id = frame_host->GetGlobalId();
+  auto it = remotes_.find(routing_id);
+  if (it == remotes_.end()) {
+    if (!should_create) {
+      return nullptr;
+    }
+    auto& bound_host = remotes_[routing_id];
+    frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
+        bound_host.BindNewEndpointAndPassReceiver());
+    return bound_host.get();
+  }
+  return it->second.get();
+}
+
 // GinJavaBridgeDispatcherHost gets created earlier than RenderProcessHost
 // is initialized. So we postpone installing the message filter until we know
 // that the RPH is in a good shape. Also, message filter installation is
 // postponed until the first named object is created.
 void GinJavaBridgeDispatcherHost::InstallFilterAndRegisterAllRoutingIds() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  CHECK(!mojo_enabled_);
+
   if (named_objects_.empty() ||
       !web_contents()->GetPrimaryMainFrame()->GetProcess()->GetChannel()) {
     return;
@@ -65,6 +114,7 @@
 void GinJavaBridgeDispatcherHost::InstallFilterAndRegisterRoutingId(
     RenderFrameHost* render_frame_host) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  CHECK(!mojo_enabled_);
   AgentSchedulingGroupHost& agent_scheduling_group =
       static_cast<RenderFrameHostImpl*>(render_frame_host)
           ->GetAgentSchedulingGroup();
@@ -94,37 +144,60 @@
     return;
   }
 
-  InstallFilterAndRegisterRoutingId(render_frame_host);
-  for (NamedObjectMap::const_iterator iter = named_objects_.begin();
-       iter != named_objects_.end();
-       ++iter) {
-    render_frame_host->Send(new GinJavaBridgeMsg_AddNamedObject(
-        render_frame_host->GetRoutingID(), iter->first, iter->second));
+  if (mojo_enabled_) {
+    mojom::GinJavaBridge* bridge =
+        GetJavaBridge(render_frame_host, /*should_create=*/true);
+    for (auto& object : named_objects_) {
+      bridge->AddNamedObject(object.first, object.second);
+    }
+  } else {
+    InstallFilterAndRegisterRoutingId(render_frame_host);
+    for (NamedObjectMap::const_iterator iter = named_objects_.begin();
+         iter != named_objects_.end(); ++iter) {
+      render_frame_host->Send(new GinJavaBridgeMsg_AddNamedObject(
+          render_frame_host->GetRoutingID(), iter->first, iter->second));
+    }
   }
 }
 
 void GinJavaBridgeDispatcherHost::RenderFrameDeleted(
     RenderFrameHost* render_frame_host) {
-  AgentSchedulingGroupHost& agent_scheduling_group =
-      static_cast<RenderFrameHostImpl*>(render_frame_host)
-          ->GetAgentSchedulingGroup();
-  scoped_refptr<GinJavaBridgeMessageFilter> filter =
-      GinJavaBridgeMessageFilter::FromHost(agent_scheduling_group,
-                                           /*create_if_not_exists=*/false);
+  if (!mojo_enabled_) {
+    AgentSchedulingGroupHost& agent_scheduling_group =
+        static_cast<RenderFrameHostImpl*>(render_frame_host)
+            ->GetAgentSchedulingGroup();
+    scoped_refptr<GinJavaBridgeMessageFilter> filter =
+        GinJavaBridgeMessageFilter::FromHost(agent_scheduling_group,
+                                             /*create_if_not_exists=*/false);
 
-  if (filter) {
-    filter->RemoveRoutingIdForHost(render_frame_host);
+    if (filter) {
+      filter->RemoveRoutingIdForHost(render_frame_host);
+    }
+  }
+  remotes_.erase(render_frame_host->GetGlobalId());
+}
+
+void GinJavaBridgeDispatcherHost::WebContentsDestroyed() {
+  if (mojo_enabled_) {
+    JavaBridgeThread::GetTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&GinJavaBridgeDispatcherHost::ClearAllReceivers, this));
   }
 }
 
 void GinJavaBridgeDispatcherHost::PrimaryPageChanged(Page& page) {
-  AgentSchedulingGroupHost& agent_scheduling_group =
-      static_cast<PageImpl&>(page).GetMainDocument().GetAgentSchedulingGroup();
-  scoped_refptr<GinJavaBridgeMessageFilter> filter =
-      GinJavaBridgeMessageFilter::FromHost(agent_scheduling_group,
-                                           /*create_if_not_exists=*/false);
-  if (!filter)
-    InstallFilterAndRegisterAllRoutingIds();
+  if (!mojo_enabled_) {
+    AgentSchedulingGroupHost& agent_scheduling_group =
+        static_cast<PageImpl&>(page)
+            .GetMainDocument()
+            .GetAgentSchedulingGroup();
+    scoped_refptr<GinJavaBridgeMessageFilter> filter =
+        GinJavaBridgeMessageFilter::FromHost(agent_scheduling_group,
+                                             /*create_if_not_exists=*/false);
+    if (!filter) {
+      InstallFilterAndRegisterAllRoutingIds();
+    }
+  }
 }
 
 GinJavaBoundObject::ObjectID GinJavaBridgeDispatcherHost::AddObject(
@@ -239,20 +312,30 @@
   }
   named_objects_[name] = object_id;
 
-  // As GinJavaBridgeDispatcherHost can be created later than WebContents has
-  // notified the observers about new RenderFrame, it is necessary to ensure
-  // here that all render frame IDs are registered with the filter.
-  InstallFilterAndRegisterAllRoutingIds();
-  // We should include pending RenderFrameHosts, otherwise they will miss the
-  // chance when calling add or remove methods when they are created but not
-  // committed. See: http://crbug.com/1087806
-  web_contents()
-      ->GetPrimaryMainFrame()
-      ->ForEachRenderFrameHostIncludingSpeculative(
-          [&name, object_id](RenderFrameHostImpl* render_frame_host) {
-            render_frame_host->Send(new GinJavaBridgeMsg_AddNamedObject(
-                render_frame_host->GetRoutingID(), name, object_id));
-          });
+  if (mojo_enabled_) {
+    web_contents()
+        ->GetPrimaryMainFrame()
+        ->ForEachRenderFrameHostIncludingSpeculative(
+            [&name, object_id, this](RenderFrameHostImpl* render_frame_host) {
+              GetJavaBridge(render_frame_host, /*should_create=*/true)
+                  ->AddNamedObject(name, object_id);
+            });
+  } else {
+    // As GinJavaBridgeDispatcherHost can be created later than WebContents has
+    // notified the observers about new RenderFrame, it is necessary to ensure
+    // here that all render frame IDs are registered with the filter.
+    InstallFilterAndRegisterAllRoutingIds();
+    // We should include pending RenderFrameHosts, otherwise they will miss the
+    // chance when calling add or remove methods when they are created but not
+    // committed. See: http://crbug.com/1087806
+    web_contents()
+        ->GetPrimaryMainFrame()
+        ->ForEachRenderFrameHostIncludingSpeculative(
+            [&name, object_id](RenderFrameHostImpl* render_frame_host) {
+              render_frame_host->Send(new GinJavaBridgeMsg_AddNamedObject(
+                  render_frame_host->GetRoutingID(), name, object_id));
+            });
+  }
 }
 
 void GinJavaBridgeDispatcherHost::RemoveNamedObject(
@@ -272,21 +355,36 @@
   }
   named_objects_.erase(iter);
 
-  // As the object isn't going to be removed from the JavaScript side until the
-  // next page reload, calls to it must still work, thus we should continue to
-  // hold it. All the transient objects and removed named objects will be purged
-  // during the cleansing caused by PrimaryMainDocumentElementAvailable event.
+  if (mojo_enabled_) {
+    web_contents()
+        ->GetPrimaryMainFrame()
+        ->ForEachRenderFrameHostIncludingSpeculative(
+            [&copied_name, this](RenderFrameHostImpl* render_frame_host) {
+              auto* bridge =
+                  GetJavaBridge(render_frame_host, /*should_create=*/false);
+              if (!bridge) {
+                return;
+              }
+              bridge->RemoveNamedObject(copied_name);
+            });
+  } else {
+    // As the object isn't going to be removed from the JavaScript side until
+    // the next page reload, calls to it must still work, thus we should
+    // continue to hold it. All the transient objects and removed named objects
+    // will be purged during the cleansing caused by
+    // PrimaryMainDocumentElementAvailable event.
 
-  // We should include pending RenderFrameHosts, otherwise they will miss the
-  // chance when calling add or remove methods when they are created but not
-  // committed. See: http://crbug.com/1087806
-  web_contents()
-      ->GetPrimaryMainFrame()
-      ->ForEachRenderFrameHostIncludingSpeculative(
-          [&copied_name](RenderFrameHostImpl* render_frame_host) {
-            render_frame_host->Send(new GinJavaBridgeMsg_RemoveNamedObject(
-                render_frame_host->GetRoutingID(), copied_name));
-          });
+    // We should include pending RenderFrameHosts, otherwise they will miss the
+    // chance when calling add or remove methods when they are created but not
+    // committed. See: http://crbug.com/1087806
+    web_contents()
+        ->GetPrimaryMainFrame()
+        ->ForEachRenderFrameHostIncludingSpeculative(
+            [&copied_name](RenderFrameHostImpl* render_frame_host) {
+              render_frame_host->Send(new GinJavaBridgeMsg_RemoveNamedObject(
+                  render_frame_host->GetRoutingID(), copied_name));
+            });
+  }
 }
 
 void GinJavaBridgeDispatcherHost::SetAllowObjectContentsInspection(bool allow) {
@@ -340,13 +438,15 @@
 
 void GinJavaBridgeDispatcherHost::OnGetMethods(
     GinJavaBoundObject::ObjectID object_id,
-    std::set<std::string>* returned_method_names) {
+    std::vector<std::string>* returned_method_names) {
   DCHECK(JavaBridgeThread::CurrentlyOn());
   if (!allow_object_contents_inspection_)
     return;
   scoped_refptr<GinJavaBoundObject> object = FindObject(object_id);
-  if (object.get())
-    *returned_method_names = object->GetMethodNames();
+  if (object.get()) {
+    std::set<std::string> result = object->GetMethodNames();
+    *returned_method_names = {result.begin(), result.end()};
+  }
 }
 
 void GinJavaBridgeDispatcherHost::OnHasMethod(
@@ -399,12 +499,10 @@
   }
 }
 
-void GinJavaBridgeDispatcherHost::OnObjectWrapperDeleted(
+void GinJavaBridgeDispatcherHost::DeleteObjectForRouteLocked(
     const GlobalRenderFrameHostId& routing_id,
     GinJavaBoundObject::ObjectID object_id) {
-  DCHECK(JavaBridgeThread::CurrentlyOn());
-  DCHECK(routing_id);
-  base::AutoLock locker(objects_lock_);
+  objects_lock_.AssertAcquired();
   auto iter = objects_.find(object_id);
   if (iter == objects_.end())
     return;
@@ -414,4 +512,78 @@
   }
 }
 
+void GinJavaBridgeDispatcherHost::OnObjectWrapperDeleted(
+    const GlobalRenderFrameHostId& routing_id,
+    GinJavaBoundObject::ObjectID object_id) {
+  CHECK(JavaBridgeThread::CurrentlyOn());
+  DCHECK(routing_id);
+  base::AutoLock locker(objects_lock_);
+  DeleteObjectForRouteLocked(routing_id, object_id);
+}
+
+void GinJavaBridgeDispatcherHost::GetObject(
+    int32_t object_id,
+    mojo::PendingReceiver<mojom::GinJavaBridgeRemoteObject> receiver) {
+  CHECK(JavaBridgeThread::CurrentlyOn());
+  if (object_receivers_.empty()) {
+    object_receivers_.set_disconnect_handler(base::BindRepeating(
+        &GinJavaBridgeDispatcherHost::ObjectDisconnected, this));
+  }
+  object_receivers_.Add(
+      this, std::move(receiver),
+      std::make_pair(receivers_.current_context(), object_id));
+}
+
+void GinJavaBridgeDispatcherHost::ObjectWrapperDeleted(int32_t object_id) {
+  CHECK(JavaBridgeThread::CurrentlyOn());
+  base::AutoLock locker(objects_lock_);
+  DeleteObjectForRouteLocked(receivers_.current_context(), object_id);
+}
+
+void GinJavaBridgeDispatcherHost::GetMethods(GetMethodsCallback callback) {
+  CHECK(JavaBridgeThread::CurrentlyOn());
+  if (!allow_object_contents_inspection_) {
+    std::move(callback).Run({});
+    return;
+  }
+  scoped_refptr<GinJavaBoundObject> object =
+      FindObject(object_receivers_.current_context().second);
+  if (object.get()) {
+    std::set<std::string> result = object->GetMethodNames();
+    std::move(callback).Run({result.begin(), result.end()});
+  } else {
+    std::move(callback).Run({});
+  }
+}
+
+void GinJavaBridgeDispatcherHost::HasMethod(const std::string& method_name,
+                                            HasMethodCallback callback) {
+  CHECK(JavaBridgeThread::CurrentlyOn());
+  scoped_refptr<GinJavaBoundObject> object =
+      FindObject(object_receivers_.current_context().second);
+  bool result = false;
+  if (object.get()) {
+    result = object->HasMethod(method_name);
+  }
+  std::move(callback).Run(result);
+}
+
+void GinJavaBridgeDispatcherHost::InvokeMethod(const std::string& method_name,
+                                               base::Value::List arguments,
+                                               InvokeMethodCallback callback) {
+  CHECK(JavaBridgeThread::CurrentlyOn());
+  base::Value::List wrapped_result;
+  content::mojom::GinJavaBridgeError error_code;
+  OnInvokeMethod(object_receivers_.current_context().first,
+                 object_receivers_.current_context().second, method_name,
+                 arguments, &wrapped_result, &error_code);
+  std::move(callback).Run(error_code, std::move(wrapped_result));
+}
+
+void GinJavaBridgeDispatcherHost::ObjectDisconnected() {
+  CHECK(JavaBridgeThread::CurrentlyOn());
+  OnObjectWrapperDeleted(object_receivers_.current_context().first,
+                         object_receivers_.current_context().second);
+}
+
 }  // namespace content
diff --git a/content/browser/android/java/gin_java_bridge_dispatcher_host.h b/content/browser/android/java/gin_java_bridge_dispatcher_host.h
index b2068fdc..166f995f 100644
--- a/content/browser/android/java/gin_java_bridge_dispatcher_host.h
+++ b/content/browser/android/java/gin_java_bridge_dispatcher_host.h
@@ -19,8 +19,12 @@
 #include "base/values.h"
 #include "content/browser/android/java/gin_java_bound_object.h"
 #include "content/browser/android/java/gin_java_method_invocation_helper.h"
+#include "content/common/buildflags.h"
+#include "content/common/gin_java_bridge.mojom.h"
 #include "content/public/browser/global_routing_id.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 
 namespace content {
 
@@ -34,6 +38,8 @@
 class GinJavaBridgeDispatcherHost
     : public base::RefCountedDeleteOnSequence<GinJavaBridgeDispatcherHost>,
       public WebContentsObserver,
+      public mojom::GinJavaBridgeHost,
+      public mojom::GinJavaBridgeRemoteObject,
       public GinJavaMethodInvocationHelper::DispatcherDelegate {
  public:
   GinJavaBridgeDispatcherHost(
@@ -54,16 +60,20 @@
   // WebContentsObserver
   void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
   void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
+  void WebContentsDestroyed() override;
   void PrimaryMainDocumentElementAvailable() override;
   void PrimaryPageChanged(Page& page) override;
 
+  void BindNewHost(GlobalRenderFrameHostId routing_id,
+                   mojo::PendingReceiver<mojom::GinJavaBridgeHost> host);
+
   // GinJavaMethodInvocationHelper::DispatcherDelegate
   JavaObjectWeakGlobalRef GetObjectWeakRef(
       GinJavaBoundObject::ObjectID object_id) override;
 
   // Run on the background thread.
   void OnGetMethods(GinJavaBoundObject::ObjectID object_id,
-                    std::set<std::string>* returned_method_names);
+                    std::vector<std::string>* returned_method_names);
   void OnHasMethod(GinJavaBoundObject::ObjectID object_id,
                    const std::string& method_name,
                    bool* result);
@@ -76,6 +86,20 @@
   void OnObjectWrapperDeleted(const GlobalRenderFrameHostId& routing_id,
                               GinJavaBoundObject::ObjectID object_id);
 
+  // mojom::GinJavaBridgeHost overrides:
+  void GetObject(int32_t object_id,
+                 mojo::PendingReceiver<mojom::GinJavaBridgeRemoteObject>
+                     receiver) override;
+  void ObjectWrapperDeleted(int32_t object_id) override;
+
+  // mojom::GinJavaBridgeRemoteObject overrides:
+  void GetMethods(GetMethodsCallback callback) override;
+  void HasMethod(const std::string& method_name,
+                 HasMethodCallback callback) override;
+  void InvokeMethod(const std::string& method_name,
+                    base::Value::List arguments,
+                    InvokeMethodCallback callback) override;
+
  private:
   friend class base::RefCountedDeleteOnSequence<GinJavaBridgeDispatcherHost>;
   friend class base::DeleteHelper<GinJavaBridgeDispatcherHost>;
@@ -85,6 +109,17 @@
 
   ~GinJavaBridgeDispatcherHost() override;
 
+  // Run on background thread.
+  void BindNewHostOnBackgroundThread(
+      GlobalRenderFrameHostId routing_id,
+      mojo::PendingReceiver<mojom::GinJavaBridgeHost> host);
+  void ClearAllReceivers();
+  void ObjectDisconnected();
+
+  // Run on the UI thread.
+  mojom::GinJavaBridge* GetJavaBridge(RenderFrameHost* frame_host,
+                                      bool should_create);
+
   // Run on the UI thread.
   void InstallFilterAndRegisterAllRoutingIds();
   void InstallFilterAndRegisterRoutingId(RenderFrameHost* render_frame_host);
@@ -103,6 +138,8 @@
   JavaObjectWeakGlobalRef RemoveHolderLocked(
       const GlobalRenderFrameHostId& holder,
       ObjectMap::iterator* iter_ptr) EXCLUSIVE_LOCKS_REQUIRED(objects_lock_);
+  void DeleteObjectForRouteLocked(const GlobalRenderFrameHostId& routing_id,
+                                  GinJavaBoundObject::ObjectID object_id);
 
   // The following objects are used only on the UI thread.
 
@@ -125,7 +162,19 @@
   base::Lock objects_lock_;
 
   // The following objects are only used on the background thread.
-  bool allow_object_contents_inspection_;
+  bool allow_object_contents_inspection_ = true;
+
+  mojo::ReceiverSet<mojom::GinJavaBridgeHost, GlobalRenderFrameHostId>
+      receivers_;
+  mojo::ReceiverSet<
+      mojom::GinJavaBridgeRemoteObject,
+      std::pair<GlobalRenderFrameHostId, GinJavaBoundObject::ObjectID>>
+      object_receivers_;
+  std::map<GlobalRenderFrameHostId,
+           mojo::AssociatedRemote<mojom::GinJavaBridge>>
+      remotes_;
+
+  const bool mojo_enabled_;
 };
 
 }  // namespace content
diff --git a/content/browser/android/java/gin_java_bridge_message_filter.cc b/content/browser/android/java/gin_java_bridge_message_filter.cc
index 1c8ae87c..83a1226 100644
--- a/content/browser/android/java/gin_java_bridge_message_filter.cc
+++ b/content/browser/android/java/gin_java_bridge_message_filter.cc
@@ -181,13 +181,13 @@
 
 void GinJavaBridgeMessageFilter::OnGetMethods(
     GinJavaBoundObject::ObjectID object_id,
-    std::set<std::string>* returned_method_names) {
+    std::vector<std::string>* returned_method_names) {
   DCHECK(JavaBridgeThread::CurrentlyOn());
   scoped_refptr<GinJavaBridgeDispatcherHost> host = FindHost();
   if (host) {
     host->OnGetMethods(object_id, returned_method_names);
   } else {
-    *returned_method_names = std::set<std::string>();
+    *returned_method_names = std::vector<std::string>();
   }
 }
 
diff --git a/content/browser/android/java/gin_java_bridge_message_filter.h b/content/browser/android/java/gin_java_bridge_message_filter.h
index bb69777..1068f3ef 100644
--- a/content/browser/android/java/gin_java_bridge_message_filter.h
+++ b/content/browser/android/java/gin_java_bridge_message_filter.h
@@ -80,7 +80,7 @@
   scoped_refptr<GinJavaBridgeDispatcherHost> FindHost(
       bool* is_in_primary_main_frame = nullptr);
   void OnGetMethods(GinJavaBoundObject::ObjectID object_id,
-                    std::set<std::string>* returned_method_names);
+                    std::vector<std::string>* returned_method_names);
   void OnHasMethod(GinJavaBoundObject::ObjectID object_id,
                    const std::string& method_name,
                    bool* result);
diff --git a/content/browser/android/javascript_injector.cc b/content/browser/android/javascript_injector.cc
index f48ff46..deefd8cc 100644
--- a/content/browser/android/javascript_injector.cc
+++ b/content/browser/android/javascript_injector.cc
@@ -77,6 +77,16 @@
   return reinterpret_cast<intptr_t>(injector);
 }
 
+void JavascriptInjector::BindGinJavaBridgeHost(
+    RenderFrameHost* host,
+    mojo::PendingReceiver<mojom::GinJavaBridgeHost> receiver) {
+  auto* injector = JavascriptInjector::FromWebContents(
+      WebContents::FromRenderFrameHost(host));
+  CHECK(injector);
+  injector->java_bridge_dispatcher_host_->BindNewHost(host->GetGlobalId(),
+                                                      std::move(receiver));
+}
+
 WEB_CONTENTS_USER_DATA_KEY_IMPL(JavascriptInjector);
 
 }  // namespace content
diff --git a/content/browser/android/javascript_injector.h b/content/browser/android/javascript_injector.h
index 3bef4891..6999fd3d9 100644
--- a/content/browser/android/javascript_injector.h
+++ b/content/browser/android/javascript_injector.h
@@ -8,11 +8,14 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_weak_ref.h"
 #include "base/android/scoped_java_ref.h"
+#include "content/common/gin_java_bridge.mojom-forward.h"
 #include "content/public/browser/web_contents_user_data.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 
 namespace content {
 
 class GinJavaBridgeDispatcherHost;
+class RenderFrameHost;
 
 class JavascriptInjector : public WebContentsUserData<JavascriptInjector> {
  public:
@@ -42,6 +45,10 @@
                        const base::android::JavaParamRef<jobject>& /* obj */,
                        const base::android::JavaParamRef<jstring>& name);
 
+  static void BindGinJavaBridgeHost(
+      RenderFrameHost* host,
+      mojo::PendingReceiver<mojom::GinJavaBridgeHost> receiver);
+
  private:
   friend class content::WebContentsUserData<JavascriptInjector>;
   // A weak reference to the Java JavascriptInjectorImpl object.
diff --git a/content/browser/attribution_reporting/attributions_browsertest.cc b/content/browser/attribution_reporting/attributions_browsertest.cc
index 2ef91543..28f6f031 100644
--- a/content/browser/attribution_reporting/attributions_browsertest.cc
+++ b/content/browser/attribution_reporting/attributions_browsertest.cc
@@ -1445,7 +1445,8 @@
             *web_contents()->GetBrowserContext()),
         /*main_frame_origin=*/
         web_contents()->GetPrimaryMainFrame()->GetLastCommittedOrigin(),
-        /*winner_origin=*/url::Origin::Create(GURL("https://a.test")));
+        /*winner_origin=*/url::Origin::Create(GURL("https://a.test")),
+        /*winner_aggregation_coordinator_origin=*/absl::nullopt);
   }
 
  private:
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index d34a332..b615ebd 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -184,8 +184,10 @@
 #include "url/origin.h"
 
 #if BUILDFLAG(IS_ANDROID)
+#include "content/browser/android/javascript_injector.h"
 #include "content/browser/android/text_suggestion_host_android.h"
 #include "content/browser/renderer_host/render_widget_host_view_android.h"
+#include "content/common/gin_java_bridge.mojom.h"
 #include "services/device/public/mojom/nfc.mojom.h"
 #include "third_party/blink/public/mojom/hid/hid.mojom.h"
 #include "third_party/blink/public/mojom/unhandled_tap_notifier/unhandled_tap_notifier.mojom.h"
@@ -1086,6 +1088,8 @@
     map->Add<device::mojom::NFC>(base::BindRepeating(
         &RenderFrameHostImpl::BindNFCReceiver, base::Unretained(host)));
   }
+  map->Add<mojom::GinJavaBridgeHost>(base::BindRepeating(
+      &JavascriptInjector::BindGinJavaBridgeHost, base::Unretained(host)));
 #else
   map->Add<blink::mojom::HidService>(base::BindRepeating(
       &RenderFrameHostImpl::GetHidService, base::Unretained(host)));
diff --git a/content/browser/devtools/protocol/emulation_handler.cc b/content/browser/devtools/protocol/emulation_handler.cc
index 1490d15..a594905 100644
--- a/content/browser/devtools/protocol/emulation_handler.cc
+++ b/content/browser/devtools/protocol/emulation_handler.cc
@@ -245,11 +245,11 @@
   }
   if (metadata->HasMinimumFrequency()) {
     virtual_sensor_metadata->minimum_frequency =
-        device::mojom::NullableDouble::New(metadata->GetMinimumFrequency(0));
+        metadata->GetMinimumFrequency(0);
   }
   if (metadata->HasMaximumFrequency()) {
     virtual_sensor_metadata->maximum_frequency =
-        device::mojom::NullableDouble::New(metadata->GetMaximumFrequency(0));
+        metadata->GetMaximumFrequency(0);
   }
   return virtual_sensor_metadata;
 }
diff --git a/content/browser/fenced_frame/fenced_frame_browsertest.cc b/content/browser/fenced_frame/fenced_frame_browsertest.cc
index 47e7317..e19bfaa 100644
--- a/content/browser/fenced_frame/fenced_frame_browsertest.cc
+++ b/content/browser/fenced_frame/fenced_frame_browsertest.cc
@@ -5016,6 +5016,7 @@
         /*main_frame_origin=*/
         web_contents()->GetPrimaryMainFrame()->GetLastCommittedOrigin(),
         /*winner_origin=*/url::Origin::Create(GURL("https://a.test")),
+        /*winner_aggregation_coordinator_origin=*/absl::nullopt,
         /*allowed_reporting_origins=*/
         {{url::Origin::Create(https_server()->GetURL("a.test", "/")),
           url::Origin::Create(https_server()->GetURL("b.test", "/")),
@@ -6905,6 +6906,14 @@
       std::string path;
     };
 
+    struct BeaconType {
+      // The name of the event type as passed into
+      // setReportEventDataForAutomaticBeacons().
+      std::string name;
+      // The mojo value that will be checked for histograms.
+      blink::mojom::AutomaticBeaconType type;
+    };
+
     Destination starting_url;
     Destination secondary_initiator_url;
     Destination navigation_url;
@@ -6938,6 +6947,10 @@
     // Whether we expect cookie data to be attached to the beacon.
     // TODO(crbug.com/1496395): Remove this after 3PCD.
     bool expected_cookie = true;
+
+    BeaconType beacon_type = {
+        blink::kFencedFrameTopNavigationCommitBeaconType,
+        blink::mojom::AutomaticBeaconType::kTopNavigationCommit};
   };
 
   static std::string DescribeParams(
@@ -6978,7 +6991,8 @@
             ->GetPrivateAggregationManager(),
         /*main_frame_origin=*/
         web_contents()->GetPrimaryMainFrame()->GetLastCommittedOrigin(),
-        /*winner_origin=*/url::Origin::Create(GURL("https://a.test")));
+        /*winner_origin=*/url::Origin::Create(GURL("https://a.test")),
+        /*winner_aggregation_coordinator_origin=*/absl::nullopt);
   }
 
   // A helper function for specifying automatic beacon tests.
@@ -7013,7 +7027,7 @@
     fenced_frame_reporter->OnUrlMappingReady(
         blink::FencedFrame::ReportingDestination::kBuyer,
         {
-            {blink::kFencedFrameTopNavigationCommitBeaconType, reporting_url},
+            {config.beacon_type.name, reporting_url},
         });
     // Set empty reporting url for seller.
     fenced_frame_reporter->OnUrlMappingReady(
@@ -7087,9 +7101,12 @@
                 destination: $2
               });
             )",
-                             blink::kFencedFrameTopNavigationCommitBeaconType,
-                             destination_list.Clone()),
+                             config.beacon_type.name, destination_list.Clone()),
                    ad_frame_execjs_options));
+
+        histogram_tester_.ExpectUniqueSample(
+            blink::kAutomaticBeaconEventTypeHistogram, config.beacon_type.type,
+            1);
       } else {
         // Call `setReportEventDataForAutomaticBeacons()` with `eventData`.
         EvalJsResult result =
@@ -7101,8 +7118,8 @@
                 destination: $3
               });
             )",
-                             blink::kFencedFrameTopNavigationCommitBeaconType,
-                             config.message.value(), destination_list.Clone()),
+                             config.beacon_type.name, config.message.value(),
+                             destination_list.Clone()),
                    ad_frame_execjs_options);
 
         if (config.message->length() > blink::kFencedFrameMaxBeaconLength) {
@@ -7114,8 +7131,15 @@
               testing::HasSubstr("The data provided to "
                                  "setReportEventDataForAutomaticBeacons() "
                                  "exceeds the maximum length, which is 64KB."));
+
+          histogram_tester_.ExpectUniqueSample(
+              blink::kAutomaticBeaconEventTypeHistogram,
+              config.beacon_type.type, 0);
         } else {
           EXPECT_TRUE(result.error.empty());
+          histogram_tester_.ExpectUniqueSample(
+              blink::kAutomaticBeaconEventTypeHistogram,
+              config.beacon_type.type, 1);
         }
       }
     }
@@ -7396,6 +7420,27 @@
   RunTest(config);
 }
 
+IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
+                       DeprecatedTopNavigation) {
+  Config config = {
+      .starting_url = {"a.test", "/fenced_frames/title1.html"},
+      .navigation_url = {"a.test", "/fenced_frames/title1.html"},
+      .beacon_type = {
+          blink::kDeprecatedFencedFrameTopNavigationBeaconType,
+          blink::mojom::AutomaticBeaconType::kDeprecatedTopNavigation}};
+  RunTest(config);
+}
+
+IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
+                       TopNavigationStart) {
+  Config config = {
+      .starting_url = {"a.test", "/fenced_frames/title1.html"},
+      .navigation_url = {"a.test", "/fenced_frames/title1.html"},
+      .beacon_type = {blink::kFencedFrameTopNavigationStartBeaconType,
+                      blink::mojom::AutomaticBeaconType::kTopNavigationStart}};
+  RunTest(config);
+}
+
 INSTANTIATE_TEST_SUITE_P(
     All,
     FencedFrameAutomaticBeaconBrowserTest,
diff --git a/content/browser/fenced_frame/fenced_frame_reporter.cc b/content/browser/fenced_frame/fenced_frame_reporter.cc
index 5d81a38..a4f8686 100644
--- a/content/browser/fenced_frame/fenced_frame_reporter.cc
+++ b/content/browser/fenced_frame/fenced_frame_reporter.cc
@@ -216,6 +216,7 @@
     PrivateAggregationManager* private_aggregation_manager,
     const url::Origin& main_frame_origin,
     const url::Origin& winner_origin,
+    const absl::optional<url::Origin>& aggregation_coordinator_origin,
     const absl::optional<std::vector<url::Origin>>& allowed_reporting_origins) {
   scoped_refptr<FencedFrameReporter> reporter =
       base::MakeRefCounted<FencedFrameReporter>(
@@ -223,7 +224,7 @@
           PrivacySandboxInvokingAPI::kProtectedAudience,
           std::move(url_loader_factory), browser_context, main_frame_origin,
           private_aggregation_manager, winner_origin,
-          allowed_reporting_origins);
+          aggregation_coordinator_origin, allowed_reporting_origins);
   reporter->direct_seller_is_seller_ = direct_seller_is_seller;
   reporter->reporting_metadata_.emplace(
       blink::FencedFrame::ReportingDestination::kBuyer,
@@ -245,6 +246,7 @@
     const url::Origin& main_frame_origin,
     PrivateAggregationManager* private_aggregation_manager,
     const absl::optional<url::Origin>& winner_origin,
+    const absl::optional<url::Origin>& winner_aggregation_coordinator_origin,
     const absl::optional<std::vector<url::Origin>>& allowed_reporting_origins)
     : url_loader_factory_(std::move(url_loader_factory)),
       attribution_manager_(
@@ -253,6 +255,8 @@
       main_frame_origin_(main_frame_origin),
       private_aggregation_manager_(private_aggregation_manager),
       winner_origin_(winner_origin),
+      winner_aggregation_coordinator_origin_(
+          winner_aggregation_coordinator_origin),
       allowed_reporting_origins_(allowed_reporting_origins),
       invoking_api_(invoking_api) {
   DCHECK(url_loader_factory_);
@@ -768,7 +772,9 @@
 
   SplitContributionsIntoBatchesThenSendToHost(
       /*requests=*/std::move(it->second), *private_aggregation_manager_,
-      /*reporting_origin=*/winner_origin_.value(), main_frame_origin_);
+      /*reporting_origin=*/winner_origin_.value(),
+      /*aggregation_coordinator_origin=*/winner_aggregation_coordinator_origin_,
+      main_frame_origin_);
 
   // Remove the entry of key `pa_event_type` from
   // `private_aggregation_event_map_` to avoid possibly sending the same
diff --git a/content/browser/fenced_frame/fenced_frame_reporter.h b/content/browser/fenced_frame/fenced_frame_reporter.h
index 2004f6a7..cbee675 100644
--- a/content/browser/fenced_frame/fenced_frame_reporter.h
+++ b/content/browser/fenced_frame/fenced_frame_reporter.h
@@ -144,6 +144,10 @@
   // `winner_origin` is the winning buyer's origin. Can be an opaque origin in
   // test iff the test does not have for event private aggregation requests.
   //
+  // `winner_aggregation_coordinator_origin` is the origin of the aggregation
+  // coordinator for the winning buyer. Set to absl::nullopt if the default
+  // coordinator should be used.
+  //
   // `allowed_reporting_origins` is the winning ad's allowedReportingOrigins. If
   //  any macro report is attempted to an unlisted origin, all further reports
   //  after it will be cancelled.
@@ -154,6 +158,7 @@
       PrivateAggregationManager* private_aggregation_manager,
       const url::Origin& main_frame_origin,
       const url::Origin& winner_origin,
+      const absl::optional<url::Origin>& winner_aggregation_coordinator_origin,
       const absl::optional<std::vector<url::Origin>>&
           allowed_reporting_origins = absl::nullopt);
 
@@ -167,6 +172,8 @@
       const url::Origin& main_frame_origin,
       PrivateAggregationManager* private_aggregation_manager = nullptr,
       const absl::optional<url::Origin>& winner_origin = absl::nullopt,
+      const absl::optional<url::Origin>& winner_aggregation_coordinator_origin =
+          absl::nullopt,
       const absl::optional<std::vector<url::Origin>>&
           allowed_reporting_origins = absl::nullopt);
 
@@ -423,6 +430,11 @@
   // The winning buyer's origin. Set to absl::nullopt for non-FLEDGE reporter.
   const absl::optional<url::Origin> winner_origin_;
 
+  // The aggregation coordinator origin for the winning buyer. Set to
+  // absl::nullopt for non-FLEDGE reporter or if the default coordinator should
+  // be used.
+  const absl::optional<url::Origin> winner_aggregation_coordinator_origin_;
+
   // Origins allowed to receive macro expanded reports.
   const absl::optional<std::vector<url::Origin>> allowed_reporting_origins_;
 
diff --git a/content/browser/fenced_frame/fenced_frame_reporter_unittest.cc b/content/browser/fenced_frame/fenced_frame_reporter_unittest.cc
index edda7d7..ace89b0c 100644
--- a/content/browser/fenced_frame/fenced_frame_reporter_unittest.cc
+++ b/content/browser/fenced_frame/fenced_frame_reporter_unittest.cc
@@ -260,7 +260,8 @@
       shared_url_loader_factory(), browser_context(),
       /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
       main_frame_origin_,
-      /*winner_origin=*/report_destination_origin_);
+      /*winner_origin=*/report_destination_origin_,
+      /*winner_aggregation_coordinator_origin=*/absl::nullopt);
   EXPECT_FALSE(reporter->SendReport(
       DestinationEnumEvent("event_type", "event_data"),
       blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
@@ -410,6 +411,7 @@
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/{{report_destination_origin_}});
 
   // Receive all mappings.
@@ -485,6 +487,7 @@
           /*direct_seller_is_seller=*/true, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/{{report_destination_origin_}});
 
   // Make reports. They should be queued, since mappings haven't been received
@@ -580,6 +583,7 @@
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/{{report_destination_origin_}});
 
   // SendReport() is called, and then a mapping is received that doesn't have
@@ -644,6 +648,7 @@
             /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
             main_frame_origin_,
             /*winner_origin=*/report_destination_origin_,
+            /*winner_aggregation_coordinator_origin=*/absl::nullopt,
             /*allowed_reporting_origins=*/test_case);
 
     // Receive buyer mapping.
@@ -679,6 +684,7 @@
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/{});
 
   // Receive a buyer mapping whose `reporting_ad_macro_map` is absl::nullopt.
@@ -712,6 +718,7 @@
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/
           {{report_destination_origin_}});
 
@@ -749,6 +756,7 @@
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/
           {{report_destination_origin_}});
 
@@ -790,6 +798,7 @@
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/
           {{report_destination_origin_}});
 
@@ -831,6 +840,7 @@
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/
           {{report_destination_origin_}});
 
@@ -871,6 +881,7 @@
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/
           {{report_destination_origin_}});
 
@@ -908,6 +919,7 @@
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/
           {{report_destination_origin_}});
 
@@ -946,6 +958,7 @@
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/
           {{report_destination_origin_}});
 
@@ -986,6 +999,7 @@
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
           /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt,
           /*allowed_reporting_origins=*/
           {{report_destination_origin_, report_destination2_origin_}});
 
@@ -1095,7 +1109,8 @@
             shared_url_loader_factory(), browser_context(),
             /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
             main_frame_origin_,
-            /*winner_origin=*/report_destination_origin_);
+            /*winner_origin=*/report_destination_origin_,
+            /*winner_aggregation_coordinator_origin=*/absl::nullopt);
 
     // SendReport() is called, but a mapping is never received.
     std::string error_message;
@@ -1118,7 +1133,8 @@
           shared_url_loader_factory(), browser_context(),
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
-          /*winner_origin=*/report_destination_origin_);
+          /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt);
 
   // Receive all non-reserved private aggregation requests.
   std::map<std::string, PrivateAggregationRequests>
@@ -1203,7 +1219,8 @@
           shared_url_loader_factory(), browser_context(),
           /*direct_seller_is_seller=*/false, &private_aggregation_manager_,
           main_frame_origin_,
-          /*winner_origin=*/report_destination_origin_);
+          /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt);
 
   // Calls SendPrivateAggregationRequestsForEvent() with event types. The event
   // types should be queued, since non-reserved private aggregation requests
@@ -1294,7 +1311,8 @@
           shared_url_loader_factory(), browser_context(),
           /*direct_seller_is_seller=*/false,
           /*private_aggregation_manager=*/nullptr, main_frame_origin_,
-          /*winner_origin=*/report_destination_origin_);
+          /*winner_origin=*/report_destination_origin_,
+          /*winner_aggregation_coordinator_origin=*/absl::nullopt);
 
   // Calls SendPrivateAggregationRequestsForEvent() with "event_type".
   // "event_type" should be ignored and not be queued.
diff --git a/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc b/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc
index 02bc4088..9e880ef 100644
--- a/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc
+++ b/content/browser/fenced_frame/fenced_frame_url_mapping_unittest.cc
@@ -143,7 +143,8 @@
         /*direct_seller_is_seller=*/false,
         /*private_aggregation_manager=*/nullptr,
         /*main_frame_origin=*/url::Origin(),
-        /*winner_origin=*/url::Origin());
+        /*winner_origin=*/url::Origin(),
+        /*winner_aggregation_coordinator_origin=*/absl::nullopt);
   }
 };
 
diff --git a/content/browser/fenced_frame/redacted_fenced_frame_config_mojom_traits_unittest.cc b/content/browser/fenced_frame/redacted_fenced_frame_config_mojom_traits_unittest.cc
index 2f5b626a..2808737 100644
--- a/content/browser/fenced_frame/redacted_fenced_frame_config_mojom_traits_unittest.cc
+++ b/content/browser/fenced_frame/redacted_fenced_frame_config_mojom_traits_unittest.cc
@@ -495,7 +495,8 @@
       /*direct_seller_is_seller=*/false,
       /*private_aggregation_manager=*/nullptr,
       /*main_frame_origin=*/url::Origin(),
-      /*winner_origin=*/url::Origin());
+      /*winner_origin=*/url::Origin(),
+      /*winner_aggregation_coordinator_origin=*/absl::nullopt);
   input_properties = properties.RedactFor(FencedFrameEntity::kEmbedder);
   EXPECT_TRUE(input_properties.has_fenced_frame_reporting());
   mojo::test::SerializeAndDeserialize<blink::mojom::FencedFrameProperties>(
diff --git a/content/browser/indexed_db/indexed_db_class_factory.cc b/content/browser/indexed_db/indexed_db_class_factory.cc
index be5e1da..4764aa9 100644
--- a/content/browser/indexed_db/indexed_db_class_factory.cc
+++ b/content/browser/indexed_db/indexed_db_class_factory.cc
@@ -21,8 +21,8 @@
 
 namespace content {
 namespace {
-DefaultLevelDBFactory* GetDefaultLevelDBFactory() {
-  static base::NoDestructor<DefaultLevelDBFactory> leveldb_factory(
+LevelDBFactory* GetLevelDBFactory() {
+  static base::NoDestructor<LevelDBFactory> leveldb_factory(
       IndexedDBClassFactory::GetLevelDBOptions(), "indexed-db");
   return leveldb_factory.get();
 }
@@ -42,7 +42,7 @@
 }
 
 IndexedDBClassFactory::IndexedDBClassFactory()
-    : leveldb_factory_(GetDefaultLevelDBFactory()),
+    : leveldb_factory_(GetLevelDBFactory()),
       transactional_leveldb_factory_(GetDefaultTransactionalLevelDBFactory()) {}
 
 // static
@@ -87,12 +87,4 @@
   }
 }
 
-void IndexedDBClassFactory::SetLevelDBFactoryForTesting(
-    LevelDBFactory* leveldb_factory) {
-  if (leveldb_factory)
-    leveldb_factory_ = leveldb_factory;
-  else
-    leveldb_factory_ = GetDefaultLevelDBFactory();
-}
-
 }  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc
index 420f525..b47b963 100644
--- a/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -114,7 +114,6 @@
         EXPECT_TRUE(success.Get());
       }
     }
-    IndexedDBClassFactory::Get()->SetLevelDBFactoryForTesting(nullptr);
     quota_manager_.reset();
     // Wait for mojo pipes to flush or there may be leaks.
     task_environment_.RunUntilIdle();
@@ -138,17 +137,6 @@
         base::SequencedTaskRunner::GetCurrentDefault());
   }
 
-  void SetUpContextWithFactories(LevelDBFactory* factory) {
-    context_ = base::MakeRefCounted<IndexedDBContextImpl>(
-        temp_dir_.GetPath(), quota_manager_proxy_.get(),
-        /*blob_storage_context=*/mojo::NullRemote(),
-        /*file_system_access_context=*/mojo::NullRemote(),
-        base::SequencedTaskRunner::GetCurrentDefault(),
-        base::SequencedTaskRunner::GetCurrentDefault());
-    if (factory)
-      IndexedDBClassFactory::Get()->SetLevelDBFactoryForTesting(factory);
-  }
-
   void RunPostedTasks() {
     base::RunLoop loop;
     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
@@ -412,7 +400,7 @@
 }
 
 TEST_F(IndexedDBFactoryTest, PreCloseTasksStart) {
-  SetUpContextWithFactories(nullptr);
+  SetUpContext();
 
   const blink::StorageKey storage_key =
       blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
@@ -519,7 +507,7 @@
 }
 
 TEST_F(IndexedDBFactoryTest, TombstoneSweeperTiming) {
-  SetUpContextWithFactories(nullptr);
+  SetUpContext();
 
   const blink::StorageKey storage_key =
       blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
@@ -560,7 +548,7 @@
 }
 
 TEST_F(IndexedDBFactoryTest, CompactionTaskTiming) {
-  SetUpContextWithFactories(nullptr);
+  SetUpContext();
 
   const blink::StorageKey storage_key =
       blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
@@ -817,10 +805,14 @@
 }
 
 TEST_F(IndexedDBFactoryTest, QuotaErrorOnDiskFull) {
-  FakeLevelDBFactory fake_ldb_factory({}, "indexed-db");
-  fake_ldb_factory.EnqueueNextOpenLevelDBStateResult(
-      nullptr, leveldb::Status::IOError("Disk is full."), true);
-  SetUpContextWithFactories(&fake_ldb_factory);
+  SetUpContext();
+  leveldb_env::SetDBFactoryForTesting(base::BindRepeating(
+      [](const leveldb_env::Options& options, const std::string& name,
+         std::unique_ptr<leveldb::DB>* dbptr) {
+        return leveldb_env::MakeIOError("foobar", "disk full",
+                                        leveldb_env::MethodID::kCreateDir,
+                                        base::File::FILE_ERROR_NO_SPACE);
+      }));
 
   // Bind the IDBFactory.
   const blink::StorageKey storage_key =
diff --git a/content/browser/interest_group/ad_auction_service_impl_unittest.cc b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
index bc80181f..e83e59c 100644
--- a/content/browser/interest_group/ad_auction_service_impl_unittest.cc
+++ b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
@@ -9306,6 +9306,177 @@
   InvokeCallbackForURN(*auction_result);
 }
 
+class AdAuctionServiceImplPrivateAggregationMultiCloudTest
+    : public AdAuctionServiceImplPrivateAggregationEnabledTest {
+ public:
+  AdAuctionServiceImplPrivateAggregationMultiCloudTest() {
+    feature_list_.InitWithFeatures(
+        /*enabled_features=*/
+        {blink::features::kPrivateAggregationApiMultipleCloudProviders,
+         aggregation_service::kAggregationServiceMultipleCloudProviders},
+        /*disabled_features=*/{});
+  }
+
+ protected:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+TEST_F(AdAuctionServiceImplPrivateAggregationMultiCloudTest,
+       PrivateAggregationReportsForwarded) {
+  // Add a mock to intercept calls to the PrivateAggregationHost.
+  class MockPrivateAggregationHost : public PrivateAggregationHost {
+   public:
+    MockPrivateAggregationHost(
+        base::RepeatingCallback<void(const absl::optional<url::Origin>&,
+                                     const url::Origin&)> check_coordinator,
+        base::RepeatingCallback<void(
+            ReportRequestGenerator,
+            std::vector<blink::mojom::AggregatableReportHistogramContribution>,
+            PrivateAggregationBudgetKey,
+            PrivateAggregationBudgeter::BudgetDeniedBehavior)>
+            on_report_request_details_received,
+        content::BrowserContext* browser_context)
+        : PrivateAggregationHost(std::move(on_report_request_details_received),
+                                 browser_context),
+          check_coordinator_(std::move(check_coordinator)) {
+      ON_CALL(*this, BindNewReceiver)
+          .WillByDefault(
+              [this](url::Origin worklet_origin, url::Origin top_frame_origin,
+                     PrivateAggregationBudgetKey::Api api_for_budgeting,
+                     absl::optional<std::string> context_id,
+                     absl::optional<base::TimeDelta> timeout,
+                     absl::optional<url::Origin> aggregation_coordinator_origin,
+                     mojo::PendingReceiver<blink::mojom::PrivateAggregationHost>
+                         pending_receiver) -> bool {
+                check_coordinator_.Run(aggregation_coordinator_origin,
+                                       worklet_origin);
+                return PrivateAggregationHost::BindNewReceiver(
+                    std::move(worklet_origin), std::move(top_frame_origin),
+                    api_for_budgeting, std::move(context_id), timeout,
+                    std::move(aggregation_coordinator_origin),
+                    std::move(pending_receiver));
+              });
+    }
+
+    ~MockPrivateAggregationHost() override = default;
+
+    MOCK_METHOD(bool,
+                BindNewReceiver,
+                (url::Origin,
+                 url::Origin,
+                 PrivateAggregationBudgetKey::Api,
+                 absl::optional<std::string>,
+                 absl::optional<base::TimeDelta>,
+                 absl::optional<url::Origin>,
+                 mojo::PendingReceiver<blink::mojom::PrivateAggregationHost>),
+                (override));
+
+   private:
+    base::RepeatingCallback<void(const absl::optional<url::Origin>&,
+                                 const url::Origin&)>
+        check_coordinator_;
+  };
+
+  class TestPrivateAggregationManagerImpl
+      : public PrivateAggregationManagerImpl {
+   public:
+    TestPrivateAggregationManagerImpl(
+        std::unique_ptr<PrivateAggregationBudgeter> budgeter,
+        std::unique_ptr<PrivateAggregationHost> host)
+        : PrivateAggregationManagerImpl(std::move(budgeter),
+                                        std::move(host),
+                                        /*storage_partition=*/nullptr) {}
+  };
+
+  constexpr char kBiddingScript[] = R"(
+function generateBid(
+    interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals,
+    browserSignals) {
+  privateAggregation.contributeToHistogram({bucket: 1n, value: 2});
+  privateAggregation.contributeToHistogram({bucket: 3n, value: 4});
+  return {'ad': 'example', 'bid': 1, 'render': 'https://example.com/render'};
+}
+
+function reportWin() {}
+)";
+
+  constexpr char kDecisionScript[] = R"(
+function scoreAd(
+    adMetadata, bid, auctionConfig, trustedScoringSignals, browserSignals) {
+      privateAggregation.contributeToHistogram({bucket: 3n, value: 4});
+  return bid;
+}
+
+function reportResult() {}
+)";
+
+  const url::Origin kAwsAggCoordinator = url::Origin::Create(
+      GURL(aggregation_service::kDefaultAggregationCoordinatorAwsCloud));
+
+  base::RunLoop run_loop;
+  base::RepeatingCallback<void(const absl::optional<url::Origin>&,
+                               const url::Origin&)>
+      check_coordinator = base::BindLambdaForTesting(
+          [&](const absl::optional<url::Origin>& got_coordinator,
+              const url::Origin& got_worklet) {
+            EXPECT_EQ(kAwsAggCoordinator, got_coordinator);
+            run_loop.Quit();
+          });
+
+  auto* storage_partition_impl = static_cast<StoragePartitionImpl*>(
+      browser_context()->GetDefaultStoragePartition());
+  auto mock_private_aggregation_host = std::make_unique<
+      MockPrivateAggregationHost>(
+      std::move(check_coordinator),
+      /*on_report_request_received=*/
+      base::BindRepeating(
+          [](PrivateAggregationHost::ReportRequestGenerator generator,
+             std::vector<blink::mojom::AggregatableReportHistogramContribution>
+                 contributions,
+             PrivateAggregationBudgetKey budget_key,
+             PrivateAggregationBudgeter::BudgetDeniedBehavior
+                 budget_denied_behavior) {
+            AggregatableReportRequest request =
+                std::move(generator).Run(contributions);
+          }),
+      /*browser_context=*/
+      storage_partition_impl->browser_context());
+  MockPrivateAggregationHost* private_aggregation_host =
+      mock_private_aggregation_host.get();
+  storage_partition_impl->OverridePrivateAggregationManagerForTesting(
+      std::make_unique<TestPrivateAggregationManagerImpl>(
+          std::make_unique<MockPrivateAggregationBudgeter>(),
+          std::move(mock_private_aggregation_host)));
+
+  network_responder_->RegisterScriptResponse(kBiddingUrlPath, kBiddingScript);
+  network_responder_->RegisterScriptResponse(kDecisionUrlPath, kDecisionScript);
+
+  blink::InterestGroup interest_group = CreateInterestGroup();
+  interest_group.bidding_url = kUrlA.Resolve(kBiddingUrlPath);
+  interest_group.priority = 2;
+  interest_group.ads.emplace();
+  blink::InterestGroup::Ad ad(
+      /*render_url=*/GURL("https://example.com/render"),
+      /*metadata=*/absl::nullopt);
+  interest_group.ads->emplace_back(std::move(ad));
+
+  interest_group.aggregation_coordinator_origin = kAwsAggCoordinator;
+  JoinInterestGroupAndFlush(interest_group);
+
+  blink::AuctionConfig auction_config;
+  auction_config.seller = kOriginA;
+  auction_config.decision_logic_url = kUrlA.Resolve(kDecisionUrlPath);
+  auction_config.non_shared_params.interest_group_buyers = {kOriginA};
+  auction_config.aggregation_coordinator_origin = kAwsAggCoordinator;
+
+  EXPECT_CALL(*private_aggregation_host, BindNewReceiver);
+
+  absl::optional<GURL> auction_result = RunAdAuctionAndFlush(auction_config);
+  EXPECT_NE(auction_result, absl::nullopt);
+  InvokeCallbackForURN(*auction_result);
+  run_loop.Run();
+}
+
 class AdAuctionServiceImplPrivateAggregationDisabledTest
     : public AdAuctionServiceImplTest {
  public:
diff --git a/content/browser/interest_group/interest_group_auction.cc b/content/browser/interest_group/interest_group_auction.cc
index 3192363..e82e307 100644
--- a/content/browser/interest_group/interest_group_auction.cc
+++ b/content/browser/interest_group/interest_group_auction.cc
@@ -353,7 +353,7 @@
     const InterestGroupAuction::PostAuctionSignals& signals,
     const absl::optional<InterestGroupAuction::PostAuctionSignals>&
         top_level_signals,
-    std::map<url::Origin,
+    std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
              InterestGroupAuctionReporter::PrivateAggregationRequests>&
         private_aggregation_requests_reserved,
     std::map<std::string,
@@ -361,8 +361,10 @@
         private_aggregation_requests_non_reserved) {
   bool is_winner = state.get() == winner;
   for (auto& [key, requests] : state->private_aggregation_requests) {
-    const url::Origin& origin = key.first;
-    InterestGroupAuction::PrivateAggregationPhase phase = key.second;
+    const url::Origin& origin = key.reporting_origin;
+    InterestGroupAuction::PrivateAggregationPhase phase = key.phase;
+    const absl::optional<url::Origin>& aggregation_coordinator_origin =
+        key.aggregation_coordinator_origin;
     double winning_bid_to_use = signals.winning_bid;
     double highest_scoring_other_bid_to_use = signals.highest_scoring_other_bid;
     // When component auctions are in use, a BuyerHelper for a component
@@ -395,14 +397,18 @@
           private_aggregation_requests_non_reserved[event_type.value()]
               .emplace_back(std::move(converted_request_value.request));
         } else {
-          private_aggregation_requests_reserved[origin].emplace_back(
-              std::move(converted_request_value.request));
+          InterestGroupAuctionReporter::PrivateAggregationKey agg_key = {
+              origin, aggregation_coordinator_origin};
+          private_aggregation_requests_reserved[std::move(agg_key)]
+              .emplace_back(std::move(converted_request_value.request));
         }
       }
     }
   }
   if (non_kanon_winner == state.get()) {
     const url::Origin& bidder = state->bidder->interest_group.owner;
+    const absl::optional<url::Origin>& aggregation_coordinator_origin =
+        state->bidder->interest_group.aggregation_coordinator_origin;
     for (auction_worklet::mojom::PrivateAggregationRequestPtr& request :
          state->non_kanon_private_aggregation_requests) {
       absl::optional<PrivateAggregationRequestWithEventType> converted_request =
@@ -414,13 +420,15 @@
                   InterestGroupAuction::PrivateAggregationPhase::kBidder),
               false);
       if (converted_request.has_value()) {
+        InterestGroupAuctionReporter::PrivateAggregationKey agg_key = {
+            bidder, aggregation_coordinator_origin};
         PrivateAggregationRequestWithEventType converted_request_value =
             std::move(converted_request.value());
         // Only reserved types are supported for k-anon failures.
         // This *should* be guaranteed by `FillInPrivateAggregationRequest`
         // since we passed in `false` for `is_winner`.
         DCHECK(!converted_request_value.event_type.has_value());
-        private_aggregation_requests_reserved[bidder].emplace_back(
+        private_aggregation_requests_reserved[std::move(agg_key)].emplace_back(
             std::move(converted_request_value.request));
       }
     }
@@ -642,6 +650,32 @@
   }
 }
 
+InterestGroupAuction::BidState::PrivateAggregationPhaseKey::
+    PrivateAggregationPhaseKey(
+        url::Origin reporting_origin,
+        PrivateAggregationPhase phase,
+        absl::optional<url::Origin> aggregation_coordinator_origin)
+    : reporting_origin(reporting_origin),
+      phase(phase),
+      aggregation_coordinator_origin(aggregation_coordinator_origin) {}
+
+InterestGroupAuction::BidState::PrivateAggregationPhaseKey::
+    PrivateAggregationPhaseKey(const PrivateAggregationPhaseKey&) = default;
+
+InterestGroupAuction::BidState::PrivateAggregationPhaseKey&
+InterestGroupAuction::BidState::PrivateAggregationPhaseKey::operator=(
+    const PrivateAggregationPhaseKey&) = default;
+
+InterestGroupAuction::BidState::PrivateAggregationPhaseKey::
+    PrivateAggregationPhaseKey(PrivateAggregationPhaseKey&&) = default;
+
+InterestGroupAuction::BidState::PrivateAggregationPhaseKey&
+InterestGroupAuction::BidState::PrivateAggregationPhaseKey::operator=(
+    PrivateAggregationPhaseKey&&) = default;
+
+InterestGroupAuction::BidState::PrivateAggregationPhaseKey::
+    ~PrivateAggregationPhaseKey() = default;
+
 InterestGroupAuction::BidState::~BidState() {
   if (trace_id.has_value()) {
     EndTracing();
@@ -1031,7 +1065,8 @@
       const BidState* non_kanon_winner,
       const PostAuctionSignals& signals,
       const absl::optional<PostAuctionSignals>& top_level_signals,
-      std::map<url::Origin, PrivateAggregationRequests>&
+      std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
+               PrivateAggregationRequests>&
           private_aggregation_requests_reserved,
       std::map<std::string, PrivateAggregationRequests>&
           private_aggregation_requests_non_reserved) {
@@ -1567,9 +1602,11 @@
                request_ptr) { return request_ptr.is_null(); }));
     auction_->MaybeLogPrivateAggregationWebFeatures(pa_requests);
     if (!pa_requests.empty()) {
+      BidState::PrivateAggregationPhaseKey agg_key = {
+          interest_group.owner, PrivateAggregationPhase::kBidder,
+          interest_group.aggregation_coordinator_origin};
       PrivateAggregationRequests& pa_requests_for_bidder =
-          state->private_aggregation_requests[std::make_pair(
-              interest_group.owner, PrivateAggregationPhase::kBidder)];
+          state->private_aggregation_requests[std::move(agg_key)];
       pa_requests_for_bidder.insert(pa_requests_for_bidder.end(),
                                     std::move_iterator(pa_requests.begin()),
                                     std::move_iterator(pa_requests.end()));
@@ -2815,8 +2852,10 @@
   // TODO(caraitto): Consider adding renderer and Mojo validation to ensure that
   // bucket sums can't be out of range, and scales can't be negative, infinite,
   // or NaN.
+  InterestGroupAuctionReporter::PrivateAggregationKey agg_key = {
+      config_->seller, config_->aggregation_coordinator_origin};
   PrivateAggregationRequests& destination_vector =
-      private_aggregation_requests_reserved_[config_->seller];
+      private_aggregation_requests_reserved_[std::move(agg_key)];
   destination_vector.push_back(
       auction_worklet::mojom::PrivateAggregationRequest::New(
           auction_worklet::mojom::AggregatableReportContribution::
@@ -2937,7 +2976,8 @@
     DCHECK(!leader.highest_scoring_other_bid_owner.has_value());
   }
 
-  std::map<url::Origin, PrivateAggregationRequests>
+  std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
+           PrivateAggregationRequests>
       private_aggregation_requests_reserved;
   std::map<std::string, PrivateAggregationRequests>
       private_aggregation_requests_non_reserved;
@@ -2968,9 +3008,9 @@
                                    debug_loss_report_urls);
   }
 
-  for (auto& [origin, requests] : private_aggregation_requests_reserved) {
+  for (auto& [key, requests] : private_aggregation_requests_reserved) {
     PrivateAggregationRequests& destination_vector =
-        private_aggregation_requests_reserved_[origin];
+        private_aggregation_requests_reserved_[key];
     destination_vector.insert(destination_vector.end(),
                               std::move_iterator(requests.begin()),
                               std::move_iterator(requests.end()));
@@ -2992,15 +3032,18 @@
   }
 }
 
-std::map<url::Origin, InterestGroupAuction::PrivateAggregationRequests>
+std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
+         InterestGroupAuction::PrivateAggregationRequests>
 InterestGroupAuction::TakeReservedPrivateAggregationRequests() {
   for (auto& component_auction_info : component_auctions_) {
-    std::map<url::Origin, PrivateAggregationRequests> requests_map =
-        component_auction_info.second->TakeReservedPrivateAggregationRequests();
-    for (auto& [origin, requests] : requests_map) {
+    std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
+             PrivateAggregationRequests>
+        requests_map = component_auction_info.second
+                           ->TakeReservedPrivateAggregationRequests();
+    for (auto& [agg_key, requests] : requests_map) {
       DCHECK(!requests.empty());
       PrivateAggregationRequests& destination_vector =
-          private_aggregation_requests_reserved_[origin];
+          private_aggregation_requests_reserved_[agg_key];
       destination_vector.insert(destination_vector.end(),
                                 std::move_iterator(requests.begin()),
                                 std::move_iterator(requests.end()));
@@ -3965,9 +4008,11 @@
     MaybeLogPrivateAggregationWebFeatures(pa_requests);
     if (!pa_requests.empty()) {
       DCHECK(config_);
+      BidState::PrivateAggregationPhaseKey agg_key = {
+          config_->seller, seller_phase(),
+          config_->aggregation_coordinator_origin};
       PrivateAggregationRequests& pa_requests_for_seller =
-          bid->bid_state->private_aggregation_requests[std::make_pair(
-              config_->seller, seller_phase())];
+          bid->bid_state->private_aggregation_requests[std::move(agg_key)];
       for (auction_worklet::mojom::PrivateAggregationRequestPtr& request :
            pa_requests) {
         // A for-event private aggregation request with non-reserved event type
diff --git a/content/browser/interest_group/interest_group_auction.h b/content/browser/interest_group/interest_group_auction.h
index c2c0cb16..c3abf36b 100644
--- a/content/browser/interest_group/interest_group_auction.h
+++ b/content/browser/interest_group/interest_group_auction.h
@@ -171,6 +171,33 @@
   };
 
   struct CONTENT_EXPORT BidState {
+    // Used as a key to group Private Aggregation API requests from worklets in
+    // a map. The `reporting_origin` and `aggregation_coordinator_origin` are
+    // passed into the Private Aggregation API.
+    struct PrivateAggregationPhaseKey {
+      PrivateAggregationPhaseKey(
+          url::Origin reporting_origin,
+          PrivateAggregationPhase phase,
+          absl::optional<url::Origin> aggregation_coordinator_origin);
+      PrivateAggregationPhaseKey(const PrivateAggregationPhaseKey& other);
+      PrivateAggregationPhaseKey& operator=(
+          const PrivateAggregationPhaseKey& other);
+      PrivateAggregationPhaseKey(PrivateAggregationPhaseKey&& other);
+      PrivateAggregationPhaseKey& operator=(PrivateAggregationPhaseKey&& other);
+      ~PrivateAggregationPhaseKey();
+
+      bool operator<(const PrivateAggregationPhaseKey& other) const {
+        return std::tie(reporting_origin, phase,
+                        aggregation_coordinator_origin) <
+               std::tie(other.reporting_origin, other.phase,
+                        other.aggregation_coordinator_origin);
+      }
+
+      url::Origin reporting_origin;
+      PrivateAggregationPhase phase;
+      absl::optional<url::Origin> aggregation_coordinator_origin;
+    };
+
     explicit BidState(const SingleStorageInterestGroup&& bidder);
     ~BidState();
 
@@ -298,13 +325,10 @@
 
     // Requests made to Private aggregation API in generateBid() and scoreAd().
     // Keyed by reporting origin of the associated requests, i.e., buyer origin
-    // for generateBid() and seller origin for scoreAd(), plus an enum that
-    // determines exactly which phase of the auction made that request.
-    //
-    // TODO(qingxinwu): Consider only saving the requests without saving Origin,
-    // since copying Origin is expensive.
-    std::map<std::pair<url::Origin, PrivateAggregationPhase>,
-             PrivateAggregationRequests>
+    // for generateBid() and seller origin for scoreAd(), an enum that
+    // determines exactly which phase of the auction made that request, and an
+    // optional aggregation coordinator origin.
+    std::map<PrivateAggregationPhaseKey, PrivateAggregationRequests>
         private_aggregation_requests;
 
     // Requests made to Private aggregation API in generateBid() for the
@@ -623,11 +647,13 @@
 
   // Retrieves all requests with reserved event type to the Private Aggregation
   // API returned by GenerateBid() and ScoreAd(). The return value is keyed by
-  // reporting origin of the associated requests. May only be called by external
-  // consumers after an auction has failed (on success, used internally to pass
-  // them to the InterestGroupAuctionReporter). May only be called once, since
-  // it takes ownership of stored reporting URLs.
-  std::map<url::Origin, PrivateAggregationRequests>
+  // reporting origin and aggregation coordinator origin of the associated
+  // requests. May only be called by external consumers after an auction has
+  // failed (on success, used internally to pass them to the
+  // InterestGroupAuctionReporter). May only be called once, since it takes
+  // ownership of stored reporting URLs.
+  std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
+           PrivateAggregationRequests>
   TakeReservedPrivateAggregationRequests();
 
   // Retrieves all requests with non-reserved event type to the Private
@@ -1287,8 +1313,10 @@
   // Stores all pending Private Aggregation API report requests of reserved
   // event type from the bidding and scoring phase. These are passed to the
   // InterestGroupAuctionReporter when it's created. Keyed by the origin of the
-  // script that issued the request (i.e. the reporting origin).
-  std::map<url::Origin, PrivateAggregationRequests>
+  // script that issued the request (i.e. the reporting origin) and the
+  // aggregation coordinator origin.
+  std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
+           PrivateAggregationRequests>
       private_aggregation_requests_reserved_;
 
   // Stores all pending Private Aggregation API report requests of non-reserved
diff --git a/content/browser/interest_group/interest_group_auction_reporter.cc b/content/browser/interest_group/interest_group_auction_reporter.cc
index ea057e2..53db7443 100644
--- a/content/browser/interest_group/interest_group_auction_reporter.cc
+++ b/content/browser/interest_group/interest_group_auction_reporter.cc
@@ -114,6 +114,30 @@
 const base::FeatureParam<int> kFledgeAdCostReportingBits{
     &kFledgeRounding, "fledge_ad_cost_reporting_bits", 8};
 
+InterestGroupAuctionReporter::PrivateAggregationKey::PrivateAggregationKey(
+    url::Origin reporting_origin,
+    absl::optional<url::Origin> aggregation_coordinator_origin)
+    : reporting_origin(std::move(reporting_origin)),
+      aggregation_coordinator_origin(
+          std::move(aggregation_coordinator_origin)) {}
+
+InterestGroupAuctionReporter::PrivateAggregationKey::PrivateAggregationKey(
+    const PrivateAggregationKey& other) = default;
+
+InterestGroupAuctionReporter::PrivateAggregationKey&
+InterestGroupAuctionReporter::PrivateAggregationKey::operator=(
+    const PrivateAggregationKey& other) = default;
+
+InterestGroupAuctionReporter::PrivateAggregationKey::PrivateAggregationKey(
+    PrivateAggregationKey&& other) = default;
+
+InterestGroupAuctionReporter::PrivateAggregationKey&
+InterestGroupAuctionReporter::PrivateAggregationKey::operator=(
+    PrivateAggregationKey&& other) = default;
+
+InterestGroupAuctionReporter::PrivateAggregationKey::~PrivateAggregationKey() =
+    default;
+
 InterestGroupAuctionReporter::SellerWinningBidInfo::SellerWinningBidInfo() =
     default;
 InterestGroupAuctionReporter::SellerWinningBidInfo::SellerWinningBidInfo(
@@ -152,7 +176,7 @@
     std::vector<GURL> debug_win_report_urls,
     std::vector<GURL> debug_loss_report_urls,
     base::flat_set<std::string> k_anon_keys_to_join,
-    std::map<url::Origin, PrivateAggregationRequests>
+    std::map<PrivateAggregationKey, PrivateAggregationRequests>
         private_aggregation_requests_reserved,
     std::map<std::string, PrivateAggregationRequests>
         private_aggregation_requests_non_reserved)
@@ -189,6 +213,8 @@
           private_aggregation_manager_,
           main_frame_origin_,
           winning_bid_info_.storage_interest_group->interest_group.owner,
+          winning_bid_info_.storage_interest_group->interest_group
+              .aggregation_coordinator_origin,
           winning_bid_info_.allowed_reporting_origins)),
       browser_context_(browser_context) {
   DCHECK(interest_group_manager_);
@@ -265,7 +291,7 @@
 void InterestGroupAuctionReporter::OnFledgePrivateAggregationRequests(
     PrivateAggregationManager* private_aggregation_manager,
     const url::Origin& main_frame_origin,
-    std::map<url::Origin,
+    std::map<PrivateAggregationKey,
              std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>>
         private_aggregation_requests) {
   // Empty vectors should've been filtered out.
@@ -280,10 +306,11 @@
     return;
   }
 
-  for (auto& [origin, requests] : private_aggregation_requests) {
+  for (auto& [agg_key, requests] : private_aggregation_requests) {
     SplitContributionsIntoBatchesThenSendToHost(
         std::move(requests), *private_aggregation_manager,
-        /*reporting_origin=*/origin, main_frame_origin);
+        /*reporting_origin=*/agg_key.reporting_origin,
+        std::move(agg_key.aggregation_coordinator_origin), main_frame_origin);
   }
 }
 
@@ -500,7 +527,6 @@
 
   log_private_aggregation_requests_callback_.Run(pa_requests);
 
-  const url::Origin& seller = seller_info->auction_config->seller;
   PrivateAggregationTimings timings;
   timings.script_run_time = reporting_latency;
   for (auction_worklet::mojom::PrivateAggregationRequestPtr& request :
@@ -520,7 +546,10 @@
     // seller.
     if (converted_request.has_value() &&
         !converted_request.value().event_type.has_value()) {
-      private_aggregation_requests_reserved_[seller].emplace_back(
+      PrivateAggregationKey agg_key = {
+          seller_info->auction_config->seller,
+          seller_info->auction_config->aggregation_coordinator_origin};
+      private_aggregation_requests_reserved_[std::move(agg_key)].emplace_back(
           std::move(converted_request.value().request));
     }
   }
@@ -798,8 +827,10 @@
 
   log_private_aggregation_requests_callback_.Run(pa_requests);
 
-  const url::Origin& bidder =
-      winning_bid_info_.storage_interest_group->interest_group.owner;
+  PrivateAggregationKey agg_key = {
+      winning_bid_info_.storage_interest_group->interest_group.owner,
+      winning_bid_info_.storage_interest_group->interest_group
+          .aggregation_coordinator_origin};
   PrivateAggregationTimings timings;
   timings.script_run_time = reporting_latency;
   for (auction_worklet::mojom::PrivateAggregationRequestPtr& request :
@@ -825,7 +856,7 @@
         private_aggregation_requests_non_reserved_[event_type.value()]
             .emplace_back(std::move(converted_request_value.request));
       } else {
-        private_aggregation_requests_reserved_[bidder].emplace_back(
+        private_aggregation_requests_reserved_[agg_key].emplace_back(
             std::move(converted_request_value.request));
       }
     }
diff --git a/content/browser/interest_group/interest_group_auction_reporter.h b/content/browser/interest_group/interest_group_auction_reporter.h
index 5e36fb0..9c77ed32 100644
--- a/content/browser/interest_group/interest_group_auction_reporter.h
+++ b/content/browser/interest_group/interest_group_auction_reporter.h
@@ -95,6 +95,27 @@
     kMaxValue = kNotStarted
   };
 
+  // Key used to group Private aggregation signals.
+  struct CONTENT_EXPORT PrivateAggregationKey {
+    PrivateAggregationKey(
+        url::Origin reporting_origin,
+        absl::optional<url::Origin> aggregation_coordinator_origin);
+    PrivateAggregationKey(const PrivateAggregationKey&);
+    PrivateAggregationKey& operator=(const PrivateAggregationKey&);
+    PrivateAggregationKey(PrivateAggregationKey&&);
+    PrivateAggregationKey& operator=(PrivateAggregationKey&&);
+    ~PrivateAggregationKey();
+
+    bool operator<(const PrivateAggregationKey& other) const {
+      return std::tie(reporting_origin, aggregation_coordinator_origin) <
+             std::tie(other.reporting_origin,
+                      other.aggregation_coordinator_origin);
+    }
+
+    url::Origin reporting_origin;
+    absl::optional<url::Origin> aggregation_coordinator_origin;
+  };
+
   using PrivateAggregationRequests =
       std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>;
 
@@ -235,7 +256,7 @@
       std::vector<GURL> debug_win_report_urls,
       std::vector<GURL> debug_loss_report_urls,
       base::flat_set<std::string> k_anon_keys_to_join,
-      std::map<url::Origin, PrivateAggregationRequests>
+      std::map<PrivateAggregationKey, PrivateAggregationRequests>
           private_aggregation_requests_reserved,
       std::map<std::string, PrivateAggregationRequests>
           private_aggregation_requests_non_reserved);
@@ -300,7 +321,7 @@
       PrivateAggregationManager* private_aggregation_manager,
       const url::Origin& main_frame_origin,
       std::map<
-          url::Origin,
+          PrivateAggregationKey,
           std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>>
           private_aggregation_requests);
 
@@ -488,7 +509,7 @@
   // Stores all pending Private Aggregation API report requests until they have
   // been flushed. Keyed by the origin of the script that issued the request
   // (i.e. the reporting origin).
-  std::map<url::Origin, PrivateAggregationRequests>
+  std::map<PrivateAggregationKey, PrivateAggregationRequests>
       private_aggregation_requests_reserved_;
   std::map<std::string, PrivateAggregationRequests>
       private_aggregation_requests_non_reserved_;
diff --git a/content/browser/interest_group/interest_group_auction_reporter_unittest.cc b/content/browser/interest_group/interest_group_auction_reporter_unittest.cc
index 35c4326..6cb5973 100644
--- a/content/browser/interest_group/interest_group_auction_reporter_unittest.cc
+++ b/content/browser/interest_group/interest_group_auction_reporter_unittest.cc
@@ -57,6 +57,9 @@
 namespace content {
 namespace {
 
+using PrivateAggregationKey =
+    InterestGroupAuctionReporter::PrivateAggregationKey;
+
 InterestGroupAuctionReporter::SellerWinningBidInfo CreateSellerWinningBidInfo(
     blink::AuctionConfig* auction_config) {
   InterestGroupAuctionReporter::SellerWinningBidInfo out;
@@ -645,7 +648,7 @@
   absl::optional<InterestGroupAuctionReporter::SellerWinningBidInfo>
       component_seller_winning_bid_info_;
   // The private aggregation requests passed in to the constructor.
-  std::map<url::Origin,
+  std::map<PrivateAggregationKey,
            InterestGroupAuctionReporter::PrivateAggregationRequests>
       private_aggregation_requests_reserved_;
 
@@ -1435,12 +1438,17 @@
 // worklet that's invoked. This covers the case where a navigation occurs before
 // the seller's reporting script completes.
 TEST_F(InterestGroupAuctionReporterTest, PrivateAggregationRequests) {
-  private_aggregation_requests_reserved_[kSellerOrigin].push_back(
-      kScoreAdPrivateAggregationRequest.Clone());
-  private_aggregation_requests_reserved_[kWinningBidderOrigin].push_back(
-      kWinningBidderGenerateBidPrivateAggregationRequest.Clone());
-  private_aggregation_requests_reserved_[kLosingBidderOrigin].push_back(
-      kLosingBidderGenerateBidPrivateAggregationRequest.Clone());
+  private_aggregation_requests_reserved_[PrivateAggregationKey(kSellerOrigin,
+                                                               absl::nullopt)]
+      .push_back(kScoreAdPrivateAggregationRequest.Clone());
+  private_aggregation_requests_reserved_[PrivateAggregationKey(
+                                             kWinningBidderOrigin,
+                                             absl::nullopt)]
+      .push_back(kWinningBidderGenerateBidPrivateAggregationRequest.Clone());
+  private_aggregation_requests_reserved_[PrivateAggregationKey(
+                                             kLosingBidderOrigin,
+                                             absl::nullopt)]
+      .push_back(kLosingBidderGenerateBidPrivateAggregationRequest.Clone());
 
   SetUpAndStartSingleSellerAuction();
 
@@ -1491,12 +1499,17 @@
 // all reporting scripts have completed.
 TEST_F(InterestGroupAuctionReporterTest,
        PrivateAggregationRequestsLateNavigation) {
-  private_aggregation_requests_reserved_[kSellerOrigin].push_back(
-      kScoreAdPrivateAggregationRequest.Clone());
-  private_aggregation_requests_reserved_[kWinningBidderOrigin].push_back(
-      kWinningBidderGenerateBidPrivateAggregationRequest.Clone());
-  private_aggregation_requests_reserved_[kLosingBidderOrigin].push_back(
-      kLosingBidderGenerateBidPrivateAggregationRequest.Clone());
+  private_aggregation_requests_reserved_[PrivateAggregationKey(kSellerOrigin,
+                                                               absl::nullopt)]
+      .push_back(kScoreAdPrivateAggregationRequest.Clone());
+  private_aggregation_requests_reserved_[PrivateAggregationKey(
+                                             kWinningBidderOrigin,
+                                             absl::nullopt)]
+      .push_back(kWinningBidderGenerateBidPrivateAggregationRequest.Clone());
+  private_aggregation_requests_reserved_[PrivateAggregationKey(
+                                             kLosingBidderOrigin,
+                                             absl::nullopt)]
+      .push_back(kLosingBidderGenerateBidPrivateAggregationRequest.Clone());
 
   SetUpAndStartSingleSellerAuction();
   EXPECT_THAT(private_aggregation_manager_.TakePrivateAggregationRequests(),
@@ -1768,8 +1781,10 @@
 // Test that nothing is recorded and no reports are sent in the case that the
 // reporting scripts are successfully run, but the frame is never navigated to.
 TEST_F(InterestGroupAuctionReporterTest, NoNavigation) {
-  private_aggregation_requests_reserved_[kWinningBidderOrigin].push_back(
-      kWinningBidderGenerateBidPrivateAggregationRequest.Clone());
+  private_aggregation_requests_reserved_[PrivateAggregationKey(
+                                             kWinningBidderOrigin,
+                                             absl::nullopt)]
+      .push_back(kWinningBidderGenerateBidPrivateAggregationRequest.Clone());
   private_aggregation_event_map_["event_type"].push_back(
       kWinningBidderGenerateBidPrivateAggregationRequest.Clone());
 
@@ -1806,8 +1821,10 @@
 // Test multiple navigations result in only a single set of reports, and
 // metadata being recorded exactly once once by the InterestGroupManager.
 TEST_F(InterestGroupAuctionReporterTest, MultipleNavigations) {
-  private_aggregation_requests_reserved_[kWinningBidderOrigin].push_back(
-      kWinningBidderGenerateBidPrivateAggregationRequest.Clone());
+  private_aggregation_requests_reserved_[PrivateAggregationKey(
+                                             kWinningBidderOrigin,
+                                             absl::nullopt)]
+      .push_back(kWinningBidderGenerateBidPrivateAggregationRequest.Clone());
   private_aggregation_event_map_["event_type"].push_back(
       kWinningBidderGenerateBidPrivateAggregationRequest.Clone());
 
diff --git a/content/browser/interest_group/interest_group_pa_report_util.cc b/content/browser/interest_group/interest_group_pa_report_util.cc
index 2adc6a6..dd66d126 100644
--- a/content/browser/interest_group/interest_group_pa_report_util.cc
+++ b/content/browser/interest_group/interest_group_pa_report_util.cc
@@ -15,8 +15,11 @@
 #include "base/check.h"
 #include "base/check_op.h"
 #include "base/containers/flat_map.h"
+#include "base/feature_list.h"
 #include "base/notreached.h"
 #include "base/numerics/clamped_math.h"
+#include "components/aggregation_service/aggregation_coordinator_utils.h"
+#include "components/aggregation_service/features.h"
 #include "content/browser/private_aggregation/private_aggregation_manager.h"
 #include "content/common/content_export.h"
 #include "content/services/auction_worklet/public/mojom/private_aggregation_request.mojom.h"
@@ -24,6 +27,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/abseil-cpp/absl/numeric/int128.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/private_aggregation/aggregatable_report.mojom.h"
 #include "third_party/blink/public/mojom/private_aggregation/private_aggregation_host.mojom.h"
 #include "url/origin.h"
@@ -315,6 +319,7 @@
     std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr> requests,
     PrivateAggregationManager& pa_manager,
     const url::Origin& reporting_origin,
+    absl::optional<url::Origin> aggregation_coordinator_origin,
     const url::Origin& main_frame_origin) {
   CHECK_EQ(reporting_origin.scheme(), url::kHttpsScheme);
   CHECK_EQ(main_frame_origin.scheme(), url::kHttpsScheme);
@@ -351,22 +356,36 @@
         std::move(request->contribution->get_histogram_contribution()));
   }
 
+  if (!base::FeatureList::IsEnabled(
+          blink::features::kPrivateAggregationApiMultipleCloudProviders) ||
+      !base::FeatureList::IsEnabled(
+          aggregation_service::kAggregationServiceMultipleCloudProviders)) {
+    // Override with the default if a non-default coordinator is specified when
+    // the feature is disabled.
+    aggregation_coordinator_origin = absl::nullopt;
+  }
+
+  if (aggregation_coordinator_origin &&
+      !aggregation_service::IsAggregationCoordinatorOriginAllowed(
+          aggregation_coordinator_origin.value())) {
+    // Ignore contributions that use an invalid coordinator.
+    return;
+  }
+
   for (auto& [debug_mode_details, contributions] : contributions_map) {
     mojo::Remote<blink::mojom::PrivateAggregationHost> remote_host;
 
-    // TODO(crbug.com/1481254): Allow specifying the
-    // `aggregation_coordinator_origin`.
     bool bound = pa_manager.BindNewReceiver(
         /*worklet_origin=*/reporting_origin,
         /*top_frame_origin=*/main_frame_origin,
         PrivateAggregationBudgetKey::Api::kProtectedAudience,
         /*context_id=*/absl::nullopt,
-        /*timeout=*/absl::nullopt,
-        /*aggregation_coordinator_origin=*/absl::nullopt,
+        /*timeout=*/absl::nullopt, aggregation_coordinator_origin,
         remote_host.BindNewPipeAndPassReceiver());
 
     // The worklet origin should be potentially trustworthy (and no context ID
-    // is set), so this should always succeed.
+    // is set) and we checked the coordinator origin, so this should always
+    // succeed.
     CHECK(bound);
 
     if (debug_mode_details->is_enabled) {
diff --git a/content/browser/interest_group/interest_group_pa_report_util.h b/content/browser/interest_group/interest_group_pa_report_util.h
index d34e1f2..02661d8 100644
--- a/content/browser/interest_group/interest_group_pa_report_util.h
+++ b/content/browser/interest_group/interest_group_pa_report_util.h
@@ -75,6 +75,7 @@
     std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr> requests,
     PrivateAggregationManager& pa_manager,
     const url::Origin& reporting_origin,
+    absl::optional<url::Origin> aggregation_coordinator_origin,
     const url::Origin& main_frame_origin);
 
 }  // namespace content
diff --git a/content/browser/media/media_devices_util.cc b/content/browser/media/media_devices_util.cc
index 80b7ebd..6cf8bb98 100644
--- a/content/browser/media/media_devices_util.cc
+++ b/content/browser/media/media_devices_util.cc
@@ -250,36 +250,30 @@
     bool has_permission,
     const MediaDeviceSaltAndOrigin& salt_and_origin,
     const blink::WebMediaDeviceInfo& device_info) {
-  bool should_show_device_ids =
-      has_permission ||
-      !base::FeatureList::IsEnabled(features::kEnumerateDevicesHideDeviceIDs);
-  return blink::WebMediaDeviceInfo(
-      should_show_device_ids
-          ? GetHMACForRawMediaDeviceID(salt_and_origin, device_info.device_id)
-          : std::string(),
-      has_permission ? device_info.label : std::string(),
-      should_show_device_ids && !device_info.group_id.empty()
-          ? GetHMACForRawMediaDeviceID(salt_and_origin, device_info.group_id,
-                                       /*use_group_salt=*/true)
-          : std::string(),
-      has_permission ? device_info.video_control_support
-                     : media::VideoCaptureControlSupport(),
-      has_permission ? device_info.video_facing
-                     : blink::mojom::FacingMode::kNone);
+  if (has_permission) {
+    return blink::WebMediaDeviceInfo(
+        GetHMACForRawMediaDeviceID(salt_and_origin, device_info.device_id),
+        device_info.label,
+        device_info.group_id.empty()
+            ? std::string()
+            : GetHMACForRawMediaDeviceID(salt_and_origin, device_info.group_id,
+                                         /*use_group_salt=*/true),
+        device_info.video_control_support, device_info.video_facing);
+  }
+  return blink::WebMediaDeviceInfo(std::string(), std::string(), std::string(),
+                                   media::VideoCaptureControlSupport(),
+                                   blink::mojom::FacingMode::kNone);
 }
 
 blink::WebMediaDeviceInfoArray TranslateMediaDeviceInfoArray(
     bool has_permission,
     const MediaDeviceSaltAndOrigin& salt_and_origin,
     const blink::WebMediaDeviceInfoArray& device_infos) {
-  const bool should_hide_device_ids_with_no_permission =
-      base::FeatureList::IsEnabled(features::kEnumerateDevicesHideDeviceIDs);
   blink::WebMediaDeviceInfoArray result;
   for (const auto& device_info : device_infos) {
     result.push_back(
         TranslateMediaDeviceInfo(has_permission, salt_and_origin, device_info));
-    if (should_hide_device_ids_with_no_permission && !has_permission &&
-        result.back().device_id.empty()) {
+    if (!has_permission && result.back().device_id.empty()) {
       break;
     }
   }
diff --git a/content/browser/media/media_devices_util.h b/content/browser/media/media_devices_util.h
index 9d6a418..e78b41a 100644
--- a/content/browser/media/media_devices_util.h
+++ b/content/browser/media/media_devices_util.h
@@ -102,20 +102,17 @@
 // `salt_and_origin`.
 // The `group_id` field is hashed using the `group_id_salt` and `origin` in
 // `salt_and_origin`.
-// If `has_permission` is false:
-//   If `features::kEnumerateDevicesHideDeviceIDs` is enabled, all fields in the
-//   returned value are empty.
-//   Otherwise, only the label field is empty.
+// If `has_permission` is false all fields in the returned value are empty.
 CONTENT_EXPORT blink::WebMediaDeviceInfo TranslateMediaDeviceInfo(
     bool has_permission,
     const MediaDeviceSaltAndOrigin& salt_and_origin,
     const blink::WebMediaDeviceInfo& device_info);
 
 // Returns a translated (HMAC) version of raw `device_infos`, with each element
-// translated using TranslateMediaDeviceInfo(). If `has_permission` is false and
-// `features::kEnumerateDevicesHideDeviceIDs` is enabled, the output will
-// contain at most one element per device type with empty values for all fields,
-// as per https://w3c.github.io/mediacapture-main/#access-control-model
+// translated using TranslateMediaDeviceInfo(). If `has_permission` is false,
+// the output will contain at most one element per device type with empty values
+// for all fields, as per
+// https://w3c.github.io/mediacapture-main/#access-control-model
 CONTENT_EXPORT blink::WebMediaDeviceInfoArray TranslateMediaDeviceInfoArray(
     bool has_permission,
     const MediaDeviceSaltAndOrigin& salt_and_origin,
diff --git a/content/browser/media/media_devices_util_browsertest.cc b/content/browser/media/media_devices_util_browsertest.cc
index 94d8b91..104b31f 100644
--- a/content/browser/media/media_devices_util_browsertest.cc
+++ b/content/browser/media/media_devices_util_browsertest.cc
@@ -4,14 +4,12 @@
 
 #include "content/browser/media/media_devices_util.h"
 
-#include "base/feature_list.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
 #include "base/test/test_future.h"
 #include "content/browser/browser_main_loop.h"
 #include "content/browser/renderer_host/media/media_devices_manager.h"
 #include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/common/features.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/global_routing_id.h"
 #include "content/public/browser/media_device_id.h"
@@ -120,11 +118,6 @@
     return future.Get();
   }
 
-  bool ShouldHideDeviceIDs() {
-    return base::FeatureList::IsEnabled(
-        features::kEnumerateDevicesHideDeviceIDs);
-  }
-
   GlobalRenderFrameHostId frame_id_;
   url::Origin origin_;
   MediaDeviceEnumeration device_enumeration_;
@@ -203,12 +196,11 @@
     blink::WebMediaDeviceInfoArray web_media_device_infos =
         TranslateMediaDeviceInfoArray(/*has_permission=*/false, salt_and_origin,
                                       device_infos);
-    EXPECT_EQ(web_media_device_infos.size(),
-              ShouldHideDeviceIDs() ? 1u : device_infos.size());
+    EXPECT_EQ(web_media_device_infos.size(), 1u);
     for (const auto& device_info : web_media_device_infos) {
-      EXPECT_EQ(device_info.device_id.empty(), ShouldHideDeviceIDs());
+      EXPECT_TRUE(device_info.device_id.empty());
       EXPECT_TRUE(device_info.label.empty());
-      EXPECT_EQ(device_info.group_id.empty(), ShouldHideDeviceIDs());
+      EXPECT_TRUE(device_info.group_id.empty());
     }
   }
 }
diff --git a/content/browser/media/media_devices_util_unittest.cc b/content/browser/media/media_devices_util_unittest.cc
index 8bae470c..f5dbe6cb 100644
--- a/content/browser/media/media_devices_util_unittest.cc
+++ b/content/browser/media/media_devices_util_unittest.cc
@@ -4,8 +4,6 @@
 
 #include "content/browser/media/media_devices_util.h"
 
-#include "base/feature_list.h"
-#include "content/common/features.h"
 #include "media/audio/audio_device_description.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -32,10 +30,6 @@
                                    /*group_id=*/"example_group_id");
 }
 
-bool ShouldHideDeviceIDs() {
-  return base::FeatureList::IsEnabled(features::kEnumerateDevicesHideDeviceIDs);
-}
-
 }  // namespace
 
 TEST(MediaDevicesUtilTest, TranslateEmptyMediaDeviceInfoArray) {
@@ -68,9 +62,9 @@
   blink::WebMediaDeviceInfo original_info = ExampleWebMediaDeviceInfo();
   blink::WebMediaDeviceInfo translated_info = TranslateMediaDeviceInfo(
       /*has_permission=*/false, salt_and_origin, original_info);
-  EXPECT_EQ(translated_info.device_id.empty(), ShouldHideDeviceIDs());
+  EXPECT_TRUE(translated_info.device_id.empty());
   EXPECT_TRUE(translated_info.label.empty());
-  EXPECT_EQ(translated_info.group_id.empty(), ShouldHideDeviceIDs());
+  EXPECT_TRUE(translated_info.group_id.empty());
 }
 
 TEST(MediaDevicesUtilTest, TranslateSpecialDeviceIDs) {
diff --git a/content/browser/preloading/prefetch/prefetch_service_unittest.cc b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
index 5ea328e..b7823bc 100644
--- a/content/browser/preloading/prefetch/prefetch_service_unittest.cc
+++ b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
@@ -44,6 +44,7 @@
 #include "content/public/test/test_renderer_host.h"
 #include "content/test/test_content_browser_client.h"
 #include "net/base/load_flags.h"
+#include "net/base/proxy_chain.h"
 #include "net/base/proxy_server.h"
 #include "net/base/request_priority.h"
 #include "services/metrics/public/cpp/metrics_utils.h"
@@ -449,13 +450,13 @@
     head->load_timing.request_start = head->load_timing.receive_headers_end -
                                       base::Milliseconds(kHeaderLatency);
 
-    head->proxy_server =
+    head->proxy_chain =
         use_prefetch_proxy
-            ? net::ProxyServer::FromSchemeHostAndPort(
+            ? net::ProxyChain::FromSchemeHostAndPort(
                   net::ProxyServer::Scheme::SCHEME_HTTPS,
                   PrefetchProxyHost(GURL(kPrefetchProxyAddress)).spec(),
                   absl::nullopt)
-            : net::ProxyServer::Direct();
+            : net::ProxyChain::Direct();
 
     head->mime_type = mime_type;
     for (const auto& header : headers) {
diff --git a/content/browser/renderer_host/clipboard_host_impl_browsertest.cc b/content/browser/renderer_host/clipboard_host_impl_browsertest.cc
index 96a3a4e..de7ddfd3 100644
--- a/content/browser/renderer_host/clipboard_host_impl_browsertest.cc
+++ b/content/browser/renderer_host/clipboard_host_impl_browsertest.cc
@@ -139,7 +139,7 @@
  public:
   ClipboardDocUrlBrowserTestP() {
     scoped_feature_list_.InitWithFeatureState(
-        blink::features::kClipboardUnsanitizedContent, GetParam());
+        blink::features::kClipboardWellFormedHtmlSanitizationWrite, GetParam());
   }
 
  private:
diff --git a/content/browser/renderer_host/media/media_devices_manager.cc b/content/browser/renderer_host/media/media_devices_manager.cc
index 49ed257..d9a419b3 100644
--- a/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/content/browser/renderer_host/media/media_devices_manager.cc
@@ -748,10 +748,9 @@
       continue;
 
     for (const auto& device_info : enumeration[i]) {
-      if (base::FeatureList::IsEnabled(
-              features::kEnumerateDevicesHideDeviceIDs) &&
-          !has_permissions[i] && !translation[i].empty())
+      if (!has_permissions[i] && !translation[i].empty()) {
         break;
+      }
 
       translation[i].push_back(TranslateMediaDeviceInfo(
           has_permissions[i], salt_and_origin, device_info));
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 9d0fedf..69a108c 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -4308,8 +4308,6 @@
     }
   }
 
-  proxy_server_ = response_head_->proxy_server;
-
   // Store the URLLoaderClient endpoints until checks have been processed.
   url_loader_client_endpoints_ = std::move(url_loader_client_endpoints);
 
@@ -8247,10 +8245,6 @@
   return navigation_entry_offset_;
 }
 
-const net::ProxyServer& NavigationRequest::GetProxyServer() {
-  return proxy_server_;
-}
-
 GlobalRenderFrameHostId NavigationRequest::GetPreviousRenderFrameHostId() {
   if (previous_render_frame_host_id_ != GlobalRenderFrameHostId()) {
     CHECK_GE(state_, READY_TO_COMMIT);
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h
index 25d4b0c..57e6180 100644
--- a/content/browser/renderer_host/navigation_request.h
+++ b/content/browser/renderer_host/navigation_request.h
@@ -51,7 +51,6 @@
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
 #include "net/base/isolation_info.h"
-#include "net/base/proxy_server.h"
 #include "net/dns/public/resolve_error_info.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "services/network/public/cpp/content_security_policy/csp_context.h"
@@ -400,7 +399,6 @@
   bool IsSignedExchangeInnerResponse() override;
   bool HasPrefetchedAlternativeSubresourceSignedExchange() override;
   bool WasResponseCached() override;
-  const net::ProxyServer& GetProxyServer() override;
   const std::string& GetHrefTranslate() override;
   const absl::optional<blink::Impression>& GetImpression() override;
   const absl::optional<blink::LocalFrameToken>& GetInitiatorFrameToken()
@@ -2283,9 +2281,6 @@
   // Unlike above, this is informational only; it does not affect the request.
   base::OnceClosure ready_to_commit_callback_for_testing_;
 
-  // Which proxy server was used for this navigation, if any.
-  net::ProxyServer proxy_server_;
-
   // Unique id that identifies the navigation for which this NavigationRequest
   // is created.
   const int64_t navigation_id_ = ++unique_id_counter_;
diff --git a/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc b/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
index 256571c..322a0e3 100644
--- a/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
+++ b/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
@@ -19,10 +19,6 @@
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
 #include "printing/printing_context.h"  // nogncheck
 #include "printing/units.h"  // nogncheck
-
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-#include "printing/printing_features.h"
-#endif
 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
 
 namespace content {
@@ -30,14 +26,6 @@
 namespace {
 
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
-bool ShouldPrintingContextSkipSystemCalls() {
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-  return printing::features::ShouldPrintJobOop();
-#else
-  return false;
-#endif
-}
-
 // Print units conversion functions.
 int32_t DeviceUnitsInPoints(int32_t device_units,
                             int32_t device_units_per_inch) {
@@ -95,7 +83,7 @@
   PrintingContextDelegate delegate;
   std::unique_ptr<printing::PrintingContext> context(
       printing::PrintingContext::Create(
-          &delegate, ShouldPrintingContextSkipSystemCalls()));
+          &delegate, printing::PrintingContext::ProcessBehavior::kOopDisabled));
   if (!context.get() ||
       context->UseDefaultSettings() != printing::mojom::ResultCode::kSuccess) {
     return PepperPrintSettingsManager::Result(PP_PrintSettings_Dev(),
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 2debb49..149e0d6 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -9007,6 +9007,9 @@
   }
   CHECK(owner_);  // See `owner_` invariants about `IsActive()`.
 
+  base::UmaHistogramEnumeration(blink::kAutomaticBeaconEventTypeHistogram,
+                                event_type);
+
   owner_->SetFencedFrameAutomaticBeaconReportEventData(
       event_type, event_data, destinations,
       attribution_reporting_runtime_features, once);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 96dbd73..a0298358 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -2182,10 +2182,6 @@
 
 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
   last_pointer_type_ = event->pointer_details().pointer_type;
-  ui::InputMethod* input_method = GetInputMethod();
-  if (window_ && window_->HasFocus() && input_method) {
-    input_method->OnTouch(event->pointer_details().pointer_type);
-  }
   event_handler_->OnTouchEvent(event);
 }
 
diff --git a/content/browser/resources/media/.eslintrc.js b/content/browser/resources/media/.eslintrc.js
deleted file mode 100644
index 3b009ac..0000000
--- a/content/browser/resources/media/.eslintrc.js
+++ /dev/null
@@ -1,10 +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.
-
-module.exports = {
-  'rules': {
-    'no-var': 'off',
-    'prefer-const': 'off',
-  },
-};
diff --git a/content/browser/resources/media/client_renderer.js b/content/browser/resources/media/client_renderer.js
index e2bcf70..ac590c8 100644
--- a/content/browser/resources/media/client_renderer.js
+++ b/content/browser/resources/media/client_renderer.js
@@ -26,7 +26,7 @@
 function createSelectableButton(
     id, groupName, buttonLabel, select_cb, isDestructed) {
   // For CSS styling.
-  var radioButton = document.createElement('input');
+  const radioButton = document.createElement('input');
   radioButton.classList.add(ClientRendererCss.SELECTABLE_BUTTON);
   radioButton.type = 'radio';
   radioButton.id = id;
@@ -38,7 +38,7 @@
   }
   buttonLabel.setAttribute('for', radioButton.id);
 
-  var fragment = document.createDocumentFragment();
+  const fragment = document.createDocumentFragment();
   fragment.appendChild(radioButton);
   fragment.appendChild(buttonLabel);
 
@@ -54,7 +54,7 @@
 function selectSelectableButton(id) {
   // |id| is usually not a valid selector for querySelector so we cannot use $
   // here.
-  var element = document.getElementById(id);
+  const element = document.getElementById(id);
   if (!element) {
     console.error('failed to select button with id: ' + id);
     return;
@@ -64,8 +64,8 @@
 }
 
 function downloadLog(text) {
-  var file = new Blob([text], {type: 'text/plain'});
-  var a = document.createElement('a');
+  const file = new Blob([text], {type: 'text/plain'});
+  const a = document.createElement('a');
   a.href = URL.createObjectURL(file);
   a.download = 'media-internals.txt';
   a.click();
@@ -74,15 +74,15 @@
 export class ClientRenderer {
   constructor() {
     this.playerListElement = $('player-list');
-    var audioTableElement = $('audio-property-table');
+    const audioTableElement = $('audio-property-table');
     if (audioTableElement) {
       this.audioPropertiesTable = audioTableElement.querySelector('tbody');
     }
-    var playerTableElement = $('player-property-table');
+    const playerTableElement = $('player-property-table');
     if (playerTableElement) {
       this.playerPropertiesTable = playerTableElement.querySelector('tbody');
     }
-    var logElement = $('log');
+    const logElement = $('log');
     if (logElement) {
       this.logTable = logElement.querySelector('tbody');
     }
@@ -90,7 +90,7 @@
     this.audioPropertyName = $('audio-property-name');
     this.audioFocusSessionListElement_ = $('audio-focus-session-list');
     this.cdmListElement_ =  $('cdm-list');
-    var generalAudioInformationTableElement = $('general-audio-info-table');
+    const generalAudioInformationTableElement = $('general-audio-info-table');
     if (generalAudioInformationTableElement) {
       this.generalAudioInformationTable =
           generalAudioInformationTableElement.querySelector('tbody');
@@ -118,17 +118,17 @@
       this.clipboardTextarea.onblur = this.hideClipboard_.bind(this);
     }
 
-    var copyPropertiesButtons =
+    const copyPropertiesButtons =
         document.getElementsByClassName('copy-properties-button');
     if (copyPropertiesButtons) {
-      for (var i = 0; i < copyPropertiesButtons.length; i++) {
+      for (let i = 0; i < copyPropertiesButtons.length; i++) {
         copyPropertiesButtons[i].onclick = this.copyProperties_.bind(this);
       }
     }
 
-    var copyLogButtons = document.getElementsByClassName('copy-log-button');
+    const copyLogButtons = document.getElementsByClassName('copy-log-button');
     if (copyLogButtons) {
-      for (var i = 0; i < copyLogButtons.length; i++) {
+      for (let i = 0; i < copyLogButtons.length; i++) {
         copyLogButtons[i].onclick = this.copyLog_.bind(this);
       }
     }
@@ -269,21 +269,21 @@
       return document.createTextNode('No formats');
     }
 
-    var table = document.createElement('table');
-    var thead = document.createElement('thead');
-    var theadRow = document.createElement('tr');
-    for (var key in formats[0]) {
-      var th = document.createElement('th');
+    const table = document.createElement('table');
+    const thead = document.createElement('thead');
+    const theadRow = document.createElement('tr');
+    for (const key in formats[0]) {
+      const th = document.createElement('th');
       th.appendChild(document.createTextNode(key));
       theadRow.appendChild(th);
     }
     thead.appendChild(theadRow);
     table.appendChild(thead);
-    var tbody = document.createElement('tbody');
-    for (var i = 0; i < formats.length; ++i) {
-      var tr = document.createElement('tr');
-      for (var key in formats[i]) {
-        var td = document.createElement('td');
+    const tbody = document.createElement('tbody');
+    for (let i = 0; i < formats.length; ++i) {
+      const tr = document.createElement('tr');
+      for (const key in formats[i]) {
+        const td = document.createElement('td');
         td.appendChild(document.createTextNode(formats[i][key]));
         tr.appendChild(td);
       }
@@ -295,21 +295,21 @@
   }
 
   redrawVideoCaptureCapabilities(videoCaptureCapabilities, keys) {
-    var copyButtonElement = $('video-capture-capabilities-copy-button');
+    const copyButtonElement = $('video-capture-capabilities-copy-button');
     copyButtonElement.onclick = function() {
       this.showClipboard(JSON.stringify(videoCaptureCapabilities, null, 2));
     }.bind(this);
 
-    var videoTableBodyElement = $('video-capture-capabilities-tbody');
+    const videoTableBodyElement = $('video-capture-capabilities-tbody');
     removeChildren(videoTableBodyElement);
 
-    for (var component in videoCaptureCapabilities) {
-      var tableRow = document.createElement('tr');
-      var device = videoCaptureCapabilities[component];
-      for (var i in keys) {
-        var value = device[keys[i]];
-        var tableCell = document.createElement('td');
-        var cellElement;
+    for (const component in videoCaptureCapabilities) {
+      const tableRow = document.createElement('tr');
+      const device = videoCaptureCapabilities[component];
+      for (const i in keys) {
+        const value = device[keys[i]];
+        const tableCell = document.createElement('td');
+        let cellElement;
         if ((typeof value) === (typeof[])) {
           cellElement = this.createVideoCaptureFormatTable(value);
         } else {
@@ -324,7 +324,7 @@
   }
 
   getAudioComponentName_(componentType, id) {
-    var baseName;
+    let baseName;
     switch (componentType) {
       case 0:
       case 1:
@@ -342,7 +342,7 @@
   }
 
   getListElementForAudioComponent_(componentType) {
-    var listElement;
+    let listElement;
     switch (componentType) {
       case 0:
         listElement = $('audio-input-controller-list');
@@ -364,22 +364,22 @@
   redrawAudioComponentList_(componentType, components) {
     // Group name imposes rule that only one component can be selected
     // (and have its properties displayed) at a time.
-    var buttonGroupName = 'audio-components';
+    const buttonGroupName = 'audio-components';
 
-    var listElement = this.getListElementForAudioComponent_(componentType);
+    const listElement = this.getListElementForAudioComponent_(componentType);
     if (!listElement) {
       console.error(
           'Failed to find list element for component type: ' + componentType);
       return;
     }
 
-    var fragment = document.createDocumentFragment();
-    for (var id in components) {
-      var li = document.createElement('li');
-      var buttonCb = this.selectAudioComponent_.bind(
+    const fragment = document.createDocumentFragment();
+    for (const id in components) {
+      const li = document.createElement('li');
+      const buttonCb = this.selectAudioComponent_.bind(
           this, componentType, id, components[id]);
-      var friendlyName = this.getAudioComponentName_(componentType, id);
-      var label = document.createElement('label');
+      const friendlyName = this.getAudioComponentName_(componentType, id);
+      const label = document.createElement('label');
       label.appendChild(document.createTextNode(friendlyName));
       li.appendChild(
           createSelectableButton(id, buttonGroupName, label, buttonCb));
@@ -414,38 +414,38 @@
 
     // Group name imposes rule that only one component can be selected
     // (and have its properties displayed) at a time.
-    var buttonGroupName = 'player-buttons';
+    const buttonGroupName = 'player-buttons';
 
-    var hasPlayers = false;
-    var fragment = document.createDocumentFragment();
-    for (var id in players) {
+    let hasPlayers = false;
+    const fragment = document.createDocumentFragment();
+    for (const id in players) {
       hasPlayers = true;
-      var player = players[id];
-      var p = player.properties;
-      var label = document.createElement('label');
+      const player = players[id];
+      const p = player.properties;
+      const label = document.createElement('label');
 
-      var nameText = p.url || 'Player ' + player.id;
-      var nameNode = document.createElement('div');
+      const nameText = p.url || 'Player ' + player.id;
+      const nameNode = document.createElement('div');
       nameNode.appendChild(document.createTextNode(nameText));
       nameNode.className = 'player-name';
       label.appendChild(nameNode);
 
-      var frame = [];
+      const frame = [];
       if (p.frame_title) {
         frame.push(p.frame_title);
       }
       if (p.frame_url) {
         frame.push(p.frame_url);
       }
-      var frameText = frame.join(' - ');
+      const frameText = frame.join(' - ');
       if (frameText) {
-        var frameNode = document.createElement('div');
+        const frameNode = document.createElement('div');
         frameNode.className = 'player-frame';
         frameNode.appendChild(document.createTextNode(frameText));
         label.appendChild(frameNode);
       }
 
-      var desc = [];
+      const desc = [];
       if (p.width && p.height) {
         desc.push(p.width + 'x' + p.height);
       }
@@ -461,16 +461,16 @@
       if (p.event) {
         desc.push('(' + p.event + ')');
       }
-      var descText = desc.join(' ');
+      const descText = desc.join(' ');
       if (descText) {
-        var descNode = document.createElement('div');
+        const descNode = document.createElement('div');
         descNode.className = 'player-desc';
         descNode.appendChild(document.createTextNode(descText));
         label.appendChild(descNode);
       }
 
-      var li = document.createElement('li');
-      var buttonCb = this.selectPlayer_.bind(this, player);
+      const li = document.createElement('li');
+      const buttonCb = this.selectPlayer_.bind(this, player);
       li.appendChild(createSelectableButton(
           id, buttonGroupName, label, buttonCb, player.destructed));
       fragment.appendChild(li);
@@ -503,17 +503,17 @@
 
   drawProperties_(propertyMap, propertiesTable) {
     removeChildren(propertiesTable);
-    var sortedKeys = Object.keys(propertyMap).sort();
-    for (var i = 0; i < sortedKeys.length; ++i) {
-      var key = sortedKeys[i];
+    const sortedKeys = Object.keys(propertyMap).sort();
+    for (let i = 0; i < sortedKeys.length; ++i) {
+      const key = sortedKeys[i];
       if (this.hiddenKeys.indexOf(key) >= 0) {
         continue;
       }
 
-      var value = propertyMap[key];
-      var row = propertiesTable.insertRow(-1);
-      var keyCell = row.insertCell(-1);
-      var valueCell = row.insertCell(-1);
+      const value = propertyMap[key];
+      const row = propertiesTable.insertRow(-1);
+      const keyCell = row.insertCell(-1);
+      const valueCell = row.insertCell(-1);
 
       keyCell.appendChild(document.createTextNode(key));
       valueCell.appendChild(document.createTextNode(JSON.stringify(value)));
@@ -522,9 +522,9 @@
 
   appendEventToLog_(event) {
     if (this.filterFunction(event.key)) {
-      var row = this.logTable.insertRow(-1);
+      const row = this.logTable.insertRow(-1);
 
-      var timestampCell = row.insertCell(-1);
+      const timestampCell = row.insertCell(-1);
       timestampCell.classList.add('timestamp');
       timestampCell.appendChild(
           document.createTextNode(millisecondsToString(event.time)));
@@ -535,16 +535,16 @@
   }
 
   drawLog_() {
-    var toDraw =
+    const toDraw =
         this.selectedPlayer.allEvents.slice(this.selectedPlayerLogIndex);
     toDraw.forEach(this.appendEventToLog_.bind(this));
     this.selectedPlayerLogIndex = this.selectedPlayer.allEvents.length;
   }
 
   saveLog_() {
-    var strippedPlayers = [];
-    for (var id in this.players) {
-      var p = this.players[id];
+    const strippedPlayers = [];
+    for (const id in this.players) {
+      const p = this.players[id];
       strippedPlayers.push({properties: p.properties, events: p.allEvents});
     }
     downloadLog(JSON.stringify(strippedPlayers, null, 2));
@@ -557,8 +557,8 @@
 
     // Copy both properties and events for convenience since both are useful
     // in bug reports.
-    var p = this.selectedPlayer;
-    var playerLog = {properties: p.properties, events: p.allEvents};
+    const p = this.selectedPlayer;
+    const playerLog = {properties: p.properties, events: p.allEvents};
 
     this.showClipboard(JSON.stringify(playerLog, null, 2));
   }
@@ -580,12 +580,12 @@
     if (!this.selectedPlayer && !this.selectedAudioCompontentData) {
       return;
     }
-    var properties =
+    const properties =
         this.selectedAudioCompontentData || this.selectedPlayer.properties;
-    var stringBuffer = [];
+    const stringBuffer = [];
 
-    for (var key in properties) {
-      var value = properties[key];
+    for (const key in properties) {
+      const value = properties[key];
       stringBuffer.push(key.toString());
       stringBuffer.push(': ');
       stringBuffer.push(value.toString());
@@ -596,14 +596,14 @@
   }
 
   onTextChange_(event) {
-    var text = this.filterText.value.toLowerCase();
-    var parts = text.split(',')
-                    .map(function(part) {
-                      return part.trim();
-                    })
-                    .filter(function(part) {
-                      return part.trim().length > 0;
-                    });
+    const text = this.filterText.value.toLowerCase();
+    const parts = text.split(',')
+                      .map(function(part) {
+                        return part.trim();
+                      })
+                      .filter(function(part) {
+                        return part.trim().length > 0;
+                      });
 
     this.filterFunction = function(text) {
       text = text.toLowerCase();
diff --git a/content/browser/resources/media/main.js b/content/browser/resources/media/main.js
index 1cb12df..a7766e9 100644
--- a/content/browser/resources/media/main.js
+++ b/content/browser/resources/media/main.js
@@ -29,7 +29,7 @@
 };
 
 window.media.onReceiveAudioStreamData = function(audioStreamData) {
-  for (var component in audioStreamData) {
+  for (const component in audioStreamData) {
     window.media.updateAudioComponent(audioStreamData[component]);
   }
 };
@@ -56,7 +56,7 @@
 };
 
 window.media.updateAudioComponent = function(component) {
-  var uniqueComponentId = component.owner_id + ':' + component.component_id;
+  const uniqueComponentId = component.owner_id + ':' + component.component_id;
   switch (component.status) {
     case 'closed':
       manager.removeAudioComponent(component.component_type, uniqueComponentId);
@@ -73,7 +73,7 @@
 };
 
 window.media.onMediaEvent = function(event) {
-  var source = event.renderer + ':' + event.player;
+  const source = event.renderer + ':' + event.player;
 
   // Although this gets called on every event, there is nothing we can do
   // because there is no onOpen event.
@@ -83,7 +83,7 @@
   manager.updatePlayerInfoNoRecord(
       source, event.ticksMillis, 'player_id', event.player);
 
-  var propertyCount = 0;
+  let propertyCount = 0;
   objectForEach(event.params, function(value, key) {
     key = key.trim();
     manager.updatePlayerInfo(source, event.ticksMillis, key, value);
diff --git a/content/browser/resources/media/manager.js b/content/browser/resources/media/manager.js
index 5f0d0ee..3383b66810 100644
--- a/content/browser/resources/media/manager.js
+++ b/content/browser/resources/media/manager.js
@@ -21,9 +21,9 @@
     this.audioComponents_ = [];
     this.clientRenderer_ = clientRenderer;
 
-    var copyAllPlayerButton = $('copy-all-player-button');
-    var copyAllAudioButton = $('copy-all-audio-button');
-    var hidePlayersButton = $('hide-players-button');
+    const copyAllPlayerButton = $('copy-all-player-button');
+    const copyAllAudioButton = $('copy-all-audio-button');
+    const hidePlayersButton = $('hide-players-button');
 
     // In tests we may not have these buttons.
     if (copyAllPlayerButton) {
@@ -83,7 +83,7 @@
     if (!(componentId in this.audioComponents_[componentType])) {
       this.audioComponents_[componentType][componentId] = componentData;
     } else {
-      for (var key in componentData) {
+      for (const key in componentData) {
         this.audioComponents_[componentType][componentId][key] =
             componentData[key];
       }
@@ -124,7 +124,7 @@
    * @param id The ID of the player to remove.
    */
   removePlayer(id) {
-    var playerRemoved = this.players_[id];
+    const playerRemoved = this.players_[id];
     delete this.players_[id];
     this.clientRenderer_.playerRemoved(this.players_, playerRemoved);
   }
@@ -175,10 +175,10 @@
      * formatDict:
      *   {'resolution':'1280x720', 'fps': '30.00', "storage: "CPU" }
      */
-    var parts = format.split(', ');
-    var formatDict = {};
-    for (var i in parts) {
-      var kv = parts[i].split(': ');
+    const parts = format.split(', ');
+    const formatDict = {};
+    for (const i in parts) {
+      let kv = parts[i].split(': ');
       if (kv.length === 2) {
         if (kv[0] === 'pixel format') {
           // The camera does not actually output I420,
@@ -201,8 +201,8 @@
 
   updateVideoCaptureCapabilities(videoCaptureCapabilities) {
     // Parse the video formats to be structured for the table.
-    for (var i in videoCaptureCapabilities) {
-      for (var j in videoCaptureCapabilities[i]['formats']) {
+    for (const i in videoCaptureCapabilities) {
+      for (const j in videoCaptureCapabilities[i]['formats']) {
         videoCaptureCapabilities[i]['formats'][j] =
             this.parseVideoCaptureFormat_(
                 videoCaptureCapabilities[i]['formats'][j]);
@@ -212,7 +212,7 @@
     }
 
     // The keys of each device to be shown in order of appearance.
-    var videoCaptureDeviceKeys =
+    const videoCaptureDeviceKeys =
         ['name', 'formats', 'captureApi', 'controlSupport', 'id'];
 
     this.clientRenderer_.redrawVideoCaptureCapabilities(
diff --git a/content/browser/resources/media/player_info.js b/content/browser/resources/media/player_info.js
index 7be18baf..fc3a66e 100644
--- a/content/browser/resources/media/player_info.js
+++ b/content/browser/resources/media/player_info.js
@@ -43,7 +43,7 @@
 
     this.properties[key] = value;
 
-    var recordValue = {
+    const recordValue = {
       time: timestamp - this.firstTimestamp_,
       key: key,
       value: value,
diff --git a/content/browser/resources/media/util.js b/content/browser/resources/media/util.js
index cb4b659..b69340a 100644
--- a/content/browser/resources/media/util.js
+++ b/content/browser/resources/media/util.js
@@ -18,7 +18,7 @@
  * @param optObj The object use as 'this' within f.
  */
 export function objectForEach(obj, f, optObj) {
-  var key;
+  let key;
   for (key in obj) {
     if (obj.hasOwnProperty(key)) {
       f.call(optObj, obj[key], key, obj);
@@ -35,7 +35,7 @@
     return num;
   }
 
-  var date = new Date(timeMillis);
+  const date = new Date(timeMillis);
   return pad(date.getUTCHours(), 2) + ':' + pad(date.getUTCMinutes(), 2) + ':' +
       pad(date.getUTCSeconds(), 2) + '.' +
       pad((date.getMilliseconds()) % 1000, 3);
diff --git a/content/browser/webid/fake_identity_request_dialog_controller.cc b/content/browser/webid/fake_identity_request_dialog_controller.cc
index 8aee013..06360e63 100644
--- a/content/browser/webid/fake_identity_request_dialog_controller.cc
+++ b/content/browser/webid/fake_identity_request_dialog_controller.cc
@@ -26,6 +26,7 @@
     IdentityRequestAccount::SignInMode sign_in_mode,
     bool show_auto_reauthn_checkbox,
     AccountSelectionCallback on_selected,
+    SigninToIdPCallback on_add_account,
     DismissCallback dismiss_callback) {
   // TODO(crbug.com/1348262): Temporarily support only the first IDP, extend to
   // support multiple IDPs.
diff --git a/content/browser/webid/fake_identity_request_dialog_controller.h b/content/browser/webid/fake_identity_request_dialog_controller.h
index 51e594f1..a6e330fb 100644
--- a/content/browser/webid/fake_identity_request_dialog_controller.h
+++ b/content/browser/webid/fake_identity_request_dialog_controller.h
@@ -35,6 +35,7 @@
       IdentityRequestAccount::SignInMode sign_in_mode,
       bool show_auto_reauthn_checkbox,
       AccountSelectionCallback on_selected,
+      SigninToIdPCallback on_add_account,
       DismissCallback dismmiss_callback) override;
 
   void ShowFailureDialog(const std::string& top_frame_for_display,
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc
index f47d4924..45b898aa 100644
--- a/content/browser/webid/federated_auth_request_impl.cc
+++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -52,7 +52,6 @@
 using blink::mojom::IdentityProviderGetParametersPtr;
 using blink::mojom::IdentityProviderRequestOptions;
 using blink::mojom::IdentityProviderRequestOptionsPtr;
-using blink::mojom::LogoutRpsStatus;
 using blink::mojom::RequestTokenStatus;
 using blink::mojom::RequestUserInfoStatus;
 using blink::mojom::RevokeStatus;
@@ -489,7 +488,6 @@
   // Ensures key data members are destructed in proper order and resolves any
   // pending promise.
   if (auth_request_token_callback_) {
-    DCHECK(!logout_callback_);
     CompleteRequestWithError(FederatedAuthRequestResult::kError,
                              TokenStatus::kUnhandledRequest,
                              /*token_error=*/absl::nullopt,
@@ -507,14 +505,6 @@
   // naturally.
   revoke_request_.reset();
 
-  if (logout_callback_) {
-    // We do not complete the logout request, so unset the
-    // PendingWebIdentityRequest on the Page so that other frames in the
-    // same Page may still trigger new requests after the current
-    // RenderFrameHost is destroyed.
-    GetPageData(&render_frame_host())->SetPendingWebIdentityRequest(nullptr);
-  }
-
   // Since FederatedAuthRequestImpl is a subclass of
   // DocumentService<blink::mojom::FederatedAuthRequest>, it only lives as long
   // as the current document.
@@ -953,66 +943,6 @@
                            /*should_delay_callback=*/false);
 }
 
-// TODO(kenrb): Depending on how this code evolves, it might make sense to
-// spin session management code into its own service. The prohibition on
-// making authentication requests and logout requests at the same time, while
-// not problematic for any plausible use case, need not be strictly necessary
-// if there is a good way to not have to resource contention between requests.
-// https://crbug.com/1200581
-void FederatedAuthRequestImpl::LogoutRps(
-    std::vector<blink::mojom::LogoutRpsRequestPtr> logout_requests,
-    LogoutRpsCallback callback) {
-  if (HasPendingRequest()) {
-    std::move(callback).Run(LogoutRpsStatus::kErrorTooManyRequests);
-    return;
-  }
-
-  DCHECK(logout_requests_.empty());
-
-  logout_callback_ = std::move(callback);
-  GetPageData(&render_frame_host())->SetPendingWebIdentityRequest(this);
-
-  if (logout_requests.empty()) {
-    CompleteLogoutRequest(LogoutRpsStatus::kError);
-    return;
-  }
-
-  if (base::ranges::any_of(logout_requests, [](auto& request) {
-        return !request->url.is_valid();
-      })) {
-    bad_message::ReceivedBadMessage(render_frame_host().GetProcess(),
-                                    bad_message::FARI_LOGOUT_BAD_ENDPOINT);
-    CompleteLogoutRequest(LogoutRpsStatus::kError);
-    return;
-  }
-
-  for (auto& request : logout_requests) {
-    logout_requests_.push(std::move(request));
-  }
-
-  if (!network::IsOriginPotentiallyTrustworthy(origin())) {
-    CompleteLogoutRequest(LogoutRpsStatus::kError);
-    return;
-  }
-
-  network_manager_ = CreateNetworkManager();
-
-  if (!IsFedCmIdpSignoutEnabled()) {
-    CompleteLogoutRequest(LogoutRpsStatus::kError);
-    return;
-  }
-
-  if (GetApiPermissionStatus(origin()) !=
-      FederatedApiPermissionStatus::GRANTED) {
-    CompleteLogoutRequest(LogoutRpsStatus::kError);
-    return;
-  }
-
-  // TODO(kenrb): These should be parallelized rather than being dispatched
-  // serially. https://crbug.com/1200581.
-  DispatchOneLogout();
-}
-
 void FederatedAuthRequestImpl::ResolveTokenRequest(
     const std::string& token,
     ResolveTokenRequestCallback callback) {
@@ -1102,8 +1032,7 @@
 bool FederatedAuthRequestImpl::HasPendingRequest() const {
   bool has_pending_request =
       GetPageData(&render_frame_host())->PendingWebIdentityRequest() != nullptr;
-  DCHECK(has_pending_request ||
-         (!auth_request_token_callback_ && !logout_callback_));
+  DCHECK(has_pending_request || !auth_request_token_callback_);
   return has_pending_request;
 }
 
@@ -1482,6 +1411,8 @@
       show_auto_reauthn_checkbox,
       base::BindOnce(&FederatedAuthRequestImpl::OnAccountSelected,
                      weak_ptr_factory_.GetWeakPtr()),
+      base::BindOnce(&FederatedAuthRequestImpl::SignInToIdP,
+                     weak_ptr_factory_.GetWeakPtr()),
       base::BindOnce(&FederatedAuthRequestImpl::OnDialogDismissed,
                      weak_ptr_factory_.GetWeakPtr()));
   devtools_instrumentation::OnFedCmDialogShown(&render_frame_host());
@@ -2118,9 +2049,6 @@
           origin(), GetEmbeddingOrigin(), url::Origin::Create(idp_config_url),
           account_id_);
 
-      permission_delegate_->GrantActiveSession(
-          origin(), url::Origin::Create(idp_config_url), account_id_);
-
       SetRequiresUserMediation(false);
 
       fedcm_metrics_->RecordTokenResponseAndTurnaroundTime(
@@ -2160,40 +2088,6 @@
   }
 }
 
-void FederatedAuthRequestImpl::DispatchOneLogout() {
-  auto logout_request = std::move(logout_requests_.front());
-  DCHECK(logout_request->url.is_valid());
-  std::string account_id = logout_request->account_id;
-  auto logout_origin = url::Origin::Create(logout_request->url);
-  logout_requests_.pop();
-
-  if (permission_delegate_->HasActiveSession(logout_origin, origin(),
-                                             account_id)) {
-    network_manager_->SendLogout(
-        logout_request->url,
-        base::BindOnce(&FederatedAuthRequestImpl::OnLogoutCompleted,
-                       weak_ptr_factory_.GetWeakPtr()));
-    permission_delegate_->RevokeActiveSession(logout_origin, origin(),
-                                              account_id);
-  } else {
-    if (logout_requests_.empty()) {
-      CompleteLogoutRequest(LogoutRpsStatus::kSuccess);
-      return;
-    }
-
-    DispatchOneLogout();
-  }
-}
-
-void FederatedAuthRequestImpl::OnLogoutCompleted() {
-  if (logout_requests_.empty()) {
-    CompleteLogoutRequest(LogoutRpsStatus::kSuccess);
-    return;
-  }
-
-  DispatchOneLogout();
-}
-
 void FederatedAuthRequestImpl::CompleteRequestWithError(
     blink::mojom::FederatedAuthRequestResult result,
     absl::optional<TokenStatus> token_status,
@@ -2376,17 +2270,6 @@
   return render_frame_host().GetMainFrame()->GetLastCommittedOrigin();
 }
 
-void FederatedAuthRequestImpl::CompleteLogoutRequest(
-    blink::mojom::LogoutRpsStatus status) {
-  network_manager_.reset();
-  base::queue<blink::mojom::LogoutRpsRequestPtr>().swap(logout_requests_);
-  if (logout_callback_) {
-    std::move(logout_callback_).Run(status);
-    logout_callback_.Reset();
-    GetPageData(&render_frame_host())->SetPendingWebIdentityRequest(nullptr);
-  }
-}
-
 void FederatedAuthRequestImpl::CompleteUserInfoRequest(
     FederatedAuthUserInfoRequest* request,
     RequestUserInfoCallback callback,
@@ -2498,7 +2381,6 @@
   if (!auth_request_token_callback_) {
     return;
   }
-  DCHECK(!logout_callback_);
   DCHECK(errors_logged_to_console_);
   CompleteRequestWithError(FederatedAuthRequestResult::kError,
                            /*token_status=*/absl::nullopt,
diff --git a/content/browser/webid/federated_auth_request_impl.h b/content/browser/webid/federated_auth_request_impl.h
index dc4197c..a5c3e168 100644
--- a/content/browser/webid/federated_auth_request_impl.h
+++ b/content/browser/webid/federated_auth_request_impl.h
@@ -83,8 +83,6 @@
   void CancelTokenRequest() override;
   void ResolveTokenRequest(const std::string& token,
                            ResolveTokenRequestCallback callback) override;
-  void LogoutRps(std::vector<blink::mojom::LogoutRpsRequestPtr> logout_requests,
-                 LogoutRpsCallback) override;
   void SetIdpSigninStatus(const url::Origin& origin,
                           blink::mojom::IdpSigninStatus status) override;
   void RegisterIdP(const ::GURL& idp, RegisterIdPCallback) override;
@@ -269,8 +267,6 @@
       blink::mojom::IdentityProviderRequestOptionsPtr idp,
       IdpNetworkRequestManager::FetchStatus status,
       const GURL& url);
-  void DispatchOneLogout();
-  void OnLogoutCompleted();
 
   void CompleteRequestWithError(
       blink::mojom::FederatedAuthRequestResult result,
@@ -287,7 +283,6 @@
       const absl::optional<GURL>& selected_idp_config_url,
       const std::string& token,
       bool should_delay_callback);
-  void CompleteLogoutRequest(blink::mojom::LogoutRpsStatus);
   void CompleteUserInfoRequest(
       FederatedAuthUserInfoRequest* request,
       RequestUserInfoCallback callback,
@@ -423,9 +418,6 @@
   // Pending revoke request.
   std::unique_ptr<FederatedAuthRevokeRequest> revoke_request_;
 
-  base::queue<blink::mojom::LogoutRpsRequestPtr> logout_requests_;
-  LogoutRpsCallback logout_callback_;
-
   // TODO(crbug.com/1361649): Refactor these member variables introduced through
   // the multi IDP prototype implementation to make them less confusing.
 
diff --git a/content/browser/webid/federated_auth_request_impl_logout_unittest.cc b/content/browser/webid/federated_auth_request_impl_logout_unittest.cc
deleted file mode 100644
index c357581..0000000
--- a/content/browser/webid/federated_auth_request_impl_logout_unittest.cc
+++ /dev/null
@@ -1,236 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/webid/federated_auth_request_impl.h"
-
-#include <memory>
-#include <ostream>
-#include <string>
-#include <utility>
-
-#include "base/functional/callback_forward.h"
-#include "base/memory/raw_ptr.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
-#include "content/browser/webid/test/delegated_idp_network_request_manager.h"
-#include "content/browser/webid/test/mock_api_permission_delegate.h"
-#include "content/browser/webid/test/mock_auto_reauthn_permission_delegate.h"
-#include "content/browser/webid/test/mock_identity_registry.h"
-#include "content/browser/webid/test/mock_identity_request_dialog_controller.h"
-#include "content/browser/webid/test/mock_idp_network_request_manager.h"
-#include "content/browser/webid/test/mock_modal_dialog_view_delegate.h"
-#include "content/browser/webid/test/mock_permission_delegate.h"
-#include "content/public/common/content_features.h"
-#include "content/test/test_render_view_host.h"
-#include "content/test/test_web_contents.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/mojom/webid/federated_auth_request.mojom.h"
-#include "ui/base/page_transition_types.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-
-using ApiPermissionStatus =
-    content::FederatedIdentityApiPermissionContextDelegate::PermissionStatus;
-using blink::mojom::LogoutRpsRequest;
-using blink::mojom::LogoutRpsRequestPtr;
-using blink::mojom::LogoutRpsStatus;
-using ::testing::_;
-using ::testing::NiceMock;
-using ::testing::Return;
-
-namespace content {
-
-namespace {
-
-constexpr char kRpUrl[] = "https://rp.example/";
-constexpr char kIdpUrl[] = "https://idp.example/";
-
-// Helper class for receiving the Logout method callback.
-class LogoutRpsRequestCallbackHelper {
- public:
-  LogoutRpsRequestCallbackHelper() = default;
-  ~LogoutRpsRequestCallbackHelper() = default;
-
-  LogoutRpsRequestCallbackHelper(const LogoutRpsRequestCallbackHelper&) =
-      delete;
-  LogoutRpsRequestCallbackHelper& operator=(
-      const LogoutRpsRequestCallbackHelper&) = delete;
-
-  LogoutRpsStatus status() const { return status_; }
-
-  // This can only be called once per lifetime of this object.
-  base::OnceCallback<void(LogoutRpsStatus)> callback() {
-    return base::BindOnce(&LogoutRpsRequestCallbackHelper::ReceiverMethod,
-                          base::Unretained(this));
-  }
-
-  // Returns when callback() is called, which can be immediately if it has
-  // already been called.
-  void WaitForCallback() {
-    if (was_called_)
-      return;
-    wait_for_callback_loop_.Run();
-  }
-
- private:
-  void ReceiverMethod(LogoutRpsStatus status) {
-    status_ = status;
-    was_called_ = true;
-    wait_for_callback_loop_.Quit();
-  }
-
-  bool was_called_ = false;
-  base::RunLoop wait_for_callback_loop_;
-  LogoutRpsStatus status_;
-};
-
-LogoutRpsRequestPtr MakeLogoutRequest(const std::string& endpoint,
-                                      const std::string& account_id) {
-  auto request = LogoutRpsRequest::New();
-  request->url = GURL(endpoint);
-  request->account_id = account_id;
-  return request;
-}
-
-class TestLogoutIdpNetworkRequestManager : public MockIdpNetworkRequestManager {
- public:
-  void SendLogout(const GURL& logout_url, LogoutCallback callback) override {
-    ++num_logout_requests_;
-    std::move(callback).Run();
-  }
-
-  size_t num_logout_requests() { return num_logout_requests_; }
-
- protected:
-  size_t num_logout_requests_{0};
-};
-
-class TestApiPermissionDelegate : public MockApiPermissionDelegate {
- public:
-  ApiPermissionStatus GetApiPermissionStatus(
-      const url::Origin& origin) override {
-    return ApiPermissionStatus::GRANTED;
-  }
-};
-
-}  // namespace
-
-class FederatedAuthRequestImplLogoutTest
-    : public RenderViewHostImplTestHarness {
- protected:
-  FederatedAuthRequestImplLogoutTest() = default;
-  ~FederatedAuthRequestImplLogoutTest() override = default;
-
-  void SetUp() override {
-    feature_list_.InitAndEnableFeature(features::kFedCmLogoutRps);
-
-    RenderViewHostImplTestHarness::SetUp();
-    test_api_permission_delegate_ =
-        std::make_unique<TestApiPermissionDelegate>();
-    mock_auto_reauthn_permission_delegate_ =
-        std::make_unique<NiceMock<MockAutoReauthnPermissionDelegate>>();
-    mock_permission_delegate_ =
-        std::make_unique<NiceMock<MockPermissionDelegate>>();
-    mock_identity_registry_ = std::make_unique<NiceMock<MockIdentityRegistry>>(
-        web_contents(), /*delegate=*/nullptr,
-        url::Origin::Create(GURL(kIdpUrl)));
-
-    static_cast<TestWebContents*>(web_contents())
-        ->NavigateAndCommit(GURL(kRpUrl), ui::PAGE_TRANSITION_LINK);
-
-    federated_auth_request_impl_ = &FederatedAuthRequestImpl::CreateForTesting(
-        *main_test_rfh(), test_api_permission_delegate_.get(),
-        mock_auto_reauthn_permission_delegate_.get(),
-        mock_permission_delegate_.get(), mock_identity_registry_.get(),
-        request_remote_.BindNewPipeAndPassReceiver());
-    auto mock_dialog_controller =
-        std::make_unique<NiceMock<MockIdentityRequestDialogController>>();
-    federated_auth_request_impl_->SetDialogControllerForTests(
-        std::move(mock_dialog_controller));
-
-    network_request_manager_ =
-        std::make_unique<TestLogoutIdpNetworkRequestManager>();
-    // DelegatedIdpNetworkRequestManager is owned by
-    // |federated_auth_request_impl_|.
-    federated_auth_request_impl_->SetNetworkManagerForTests(
-        std::make_unique<DelegatedIdpNetworkRequestManager>(
-            network_request_manager_.get()));
-
-    federated_auth_request_impl_->SetTokenRequestDelayForTests(
-        base::TimeDelta());
-  }
-
-  void TearDown() override {
-    federated_auth_request_impl_ = nullptr;
-    RenderViewHostImplTestHarness::TearDown();
-  }
-
-  LogoutRpsStatus PerformLogoutRequest(
-      std::vector<LogoutRpsRequestPtr> logout_requests) {
-    LogoutRpsRequestCallbackHelper logout_helper;
-    request_remote_->LogoutRps(std::move(logout_requests),
-                               logout_helper.callback());
-    logout_helper.WaitForCallback();
-    return logout_helper.status();
-  }
-
- protected:
-  base::test::ScopedFeatureList feature_list_;
-
-  mojo::Remote<blink::mojom::FederatedAuthRequest> request_remote_;
-  raw_ptr<FederatedAuthRequestImpl> federated_auth_request_impl_;
-
-  std::unique_ptr<TestLogoutIdpNetworkRequestManager> network_request_manager_;
-
-  std::unique_ptr<TestApiPermissionDelegate> test_api_permission_delegate_;
-  std::unique_ptr<NiceMock<MockAutoReauthnPermissionDelegate>>
-      mock_auto_reauthn_permission_delegate_;
-  std::unique_ptr<NiceMock<MockPermissionDelegate>> mock_permission_delegate_;
-  std::unique_ptr<NiceMock<MockIdentityRegistry>> mock_identity_registry_;
-};
-
-// Test Logout method success with multiple relying parties.
-TEST_F(FederatedAuthRequestImplLogoutTest, LogoutSuccessMultiple) {
-  std::vector<LogoutRpsRequestPtr> logout_requests;
-  logout_requests.push_back(
-      MakeLogoutRequest("https://rp1.example", "user123"));
-  logout_requests.push_back(
-      MakeLogoutRequest("https://rp2.example", "user456"));
-  logout_requests.push_back(
-      MakeLogoutRequest("https://rp3.example", "user789"));
-
-  for (int i = 0; i < 3; ++i) {
-    EXPECT_CALL(*mock_permission_delegate_, HasActiveSession(_, _, _))
-        .WillOnce(Return(true))
-        .RetiresOnSaturation();
-  }
-
-  auto logout_response = PerformLogoutRequest(std::move(logout_requests));
-  EXPECT_EQ(logout_response, LogoutRpsStatus::kSuccess);
-  EXPECT_EQ(3u, static_cast<TestLogoutIdpNetworkRequestManager*>(
-                    network_request_manager_.get())
-                    ->num_logout_requests());
-}
-
-// Test Logout without session permission granted.
-TEST_F(FederatedAuthRequestImplLogoutTest, LogoutWithoutPermission) {
-  std::vector<LogoutRpsRequestPtr> logout_requests;
-  logout_requests.push_back(
-      MakeLogoutRequest("https://rp1.example", "user123"));
-
-  auto logout_response = PerformLogoutRequest(std::move(logout_requests));
-  EXPECT_EQ(logout_response, LogoutRpsStatus::kSuccess);
-}
-
-// Test Logout method with an empty endpoint vector.
-TEST_F(FederatedAuthRequestImplLogoutTest, LogoutNoEndpoints) {
-  auto logout_response =
-      PerformLogoutRequest(std::vector<LogoutRpsRequestPtr>());
-  EXPECT_EQ(logout_response, LogoutRpsStatus::kError);
-}
-
-}  // namespace content
diff --git a/content/browser/webid/federated_auth_request_impl_multiple_frames_unittest.cc b/content/browser/webid/federated_auth_request_impl_multiple_frames_unittest.cc
index ab5864f..1c9c82f 100644
--- a/content/browser/webid/federated_auth_request_impl_multiple_frames_unittest.cc
+++ b/content/browser/webid/federated_auth_request_impl_multiple_frames_unittest.cc
@@ -167,6 +167,7 @@
       IdentityRequestAccount::SignInMode sign_in_mode,
       bool show_auto_reauthn_checkbox,
       IdentityRequestDialogController::AccountSelectionCallback on_selected,
+      IdentityRequestDialogController::SigninToIdPCallback on_add_account,
       IdentityRequestDialogController::DismissCallback dismiss_callback)
       override {
     state_->did_show_accounts_dialog = true;
diff --git a/content/browser/webid/federated_auth_request_impl_registry_unittest.cc b/content/browser/webid/federated_auth_request_impl_registry_unittest.cc
index 4a0c08d..fce2348 100644
--- a/content/browser/webid/federated_auth_request_impl_registry_unittest.cc
+++ b/content/browser/webid/federated_auth_request_impl_registry_unittest.cc
@@ -36,9 +36,6 @@
 
 using ApiPermissionStatus =
     content::FederatedIdentityApiPermissionContextDelegate::PermissionStatus;
-using blink::mojom::LogoutRpsRequest;
-using blink::mojom::LogoutRpsRequestPtr;
-using blink::mojom::LogoutRpsStatus;
 using ::testing::_;
 using ::testing::NiceMock;
 using ::testing::Return;
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc
index bb5bb49..5c6a636 100644
--- a/content/browser/webid/federated_auth_request_impl_unittest.cc
+++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -667,6 +667,7 @@
       IdentityRequestAccount::SignInMode sign_in_mode,
       bool show_auto_reauthn_checkbox,
       IdentityRequestDialogController::AccountSelectionCallback on_selected,
+      IdentityRequestDialogController::SigninToIdPCallback on_add_account,
       IdentityRequestDialogController::DismissCallback dismiss_callback)
       override {
     if (!state_) {
@@ -2942,6 +2943,7 @@
       SignInMode sign_in_mode,
       bool show_auto_reauthn_checkbox,
       IdentityRequestDialogController::AccountSelectionCallback on_selected,
+      IdentityRequestDialogController::SigninToIdPCallback on_add_account,
       IdentityRequestDialogController::DismissCallback dismiss_callback)
       override {
     // Disable FedCM API
@@ -2953,7 +2955,7 @@
         top_frame_for_display, iframe_for_display,
         std::move(identity_provider_data), sign_in_mode,
         show_auto_reauthn_checkbox, std::move(on_selected),
-        std::move(dismiss_callback));
+        std::move(on_add_account), std::move(dismiss_callback));
   }
 
  private:
diff --git a/content/browser/webid/flags.cc b/content/browser/webid/flags.cc
index a0c1e06..3e8b145 100644
--- a/content/browser/webid/flags.cc
+++ b/content/browser/webid/flags.cc
@@ -16,10 +16,6 @@
   return base::FeatureList::IsEnabled(features::kFedCmAuthz);
 }
 
-bool IsFedCmIdpSignoutEnabled() {
-  return base::FeatureList::IsEnabled(features::kFedCmLogoutRps);
-}
-
 bool IsFedCmMultipleIdentityProvidersEnabled() {
   return base::FeatureList::IsEnabled(
       features::kFedCmMultipleIdentityProviders);
diff --git a/content/browser/webid/flags.h b/content/browser/webid/flags.h
index f63c10d..1bba553f 100644
--- a/content/browser/webid/flags.h
+++ b/content/browser/webid/flags.h
@@ -15,9 +15,6 @@
 // Whether the AuthZ is enabled or not.
 bool IsFedCmAuthzEnabled();
 
-// Whether FedCM IDP sign-out is enabled.
-bool IsFedCmIdpSignoutEnabled();
-
 // Whether multiple identity providers are enabled.
 bool IsFedCmMultipleIdentityProvidersEnabled();
 
diff --git a/content/browser/webid/test/mock_identity_request_dialog_controller.h b/content/browser/webid/test/mock_identity_request_dialog_controller.h
index d137121..8400d60 100644
--- a/content/browser/webid/test/mock_identity_request_dialog_controller.h
+++ b/content/browser/webid/test/mock_identity_request_dialog_controller.h
@@ -23,13 +23,14 @@
   MockIdentityRequestDialogController& operator=(
       const MockIdentityRequestDialogController&) = delete;
 
-  MOCK_METHOD7(ShowAccountsDialog,
+  MOCK_METHOD8(ShowAccountsDialog,
                void(const std::string&,
                     const absl::optional<std::string>&,
                     const std::vector<content::IdentityProviderData>&,
                     IdentityRequestAccount::SignInMode,
                     bool,
                     AccountSelectionCallback,
+                    SigninToIdPCallback,
                     DismissCallback));
   MOCK_METHOD0(DestructorCalled, void());
   MOCK_METHOD7(ShowFailureDialog,
diff --git a/content/browser/webid/webid_browsertest.cc b/content/browser/webid/webid_browsertest.cc
index 505682a..cb519d0 100644
--- a/content/browser/webid/webid_browsertest.cc
+++ b/content/browser/webid/webid_browsertest.cc
@@ -967,7 +967,7 @@
           test_browser_client_->GetIdentityRequestDialogControllerForTests());
 
   // Expects the account chooser to be opened. Selects the first account.
-  EXPECT_CALL(*controller, ShowAccountsDialog(_, _, _, _, _, _, _))
+  EXPECT_CALL(*controller, ShowAccountsDialog(_, _, _, _, _, _, _, _))
       .WillOnce(::testing::WithArg<5>([&config_url](auto on_selected) {
         std::move(on_selected)
             .Run(config_url,
diff --git a/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
index cd0cdbe..419e2cf6 100644
--- a/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
+++ b/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
@@ -234,7 +234,7 @@
 // TODO(crbug.com/1126373): The test is flaky on multiple platforms.
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) ||    \
     BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_FUCHSIA) || \
-    BUILDFLAG(IS_IOS)
+    BUILDFLAG(IS_IOS) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 #define MAYBE_AddingAndRemovingVirtualDeviceTriggersMediaElementOnDeviceChange \
   DISABLED_AddingAndRemovingVirtualDeviceTriggersMediaElementOnDeviceChange
 #else
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 9c47162..d1b3e62 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -234,8 +234,6 @@
      kDefault},
     {wf::EnableFedCmIdpSigninStatus,
      raw_ref(features::kFedCmIdpSigninStatusEnabled), kSetOnlyIfOverridden},
-    {wf::EnableFedCmIdpSignout, raw_ref(features::kFedCmLogoutRps),
-     kSetOnlyIfOverridden},
     {wf::EnableGamepadMultitouch, raw_ref(features::kEnableGamepadMultitouch)},
     {wf::EnableSharedStorageAPI,
      raw_ref(features::kPrivacySandboxAdsAPIsOverride), kSetOnlyIfOverridden},
diff --git a/content/common/features.cc b/content/common/features.cc
index 29bfbe9..0f0d93e 100644
--- a/content/common/features.cc
+++ b/content/common/features.cc
@@ -167,13 +167,6 @@
              "EnsureAllowBindingsIsAlwaysForWebUI",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-// If this feature is enabled and device permission is not granted by the user,
-// media-device enumeration will provide at most one device per type and the
-// device IDs will not be available.
-BASE_FEATURE(kEnumerateDevicesHideDeviceIDs,
-             "EnumerateDevicesHideDeviceIDs",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 // Content counterpart of ExperimentalContentSecurityPolicyFeatures in
 // third_party/blink/renderer/platform/runtime_enabled_features.json5. Enables
 // experimental Content Security Policy features ('navigate-to').
diff --git a/content/common/features.gni b/content/common/features.gni
index 111edf6..ee50f20 100644
--- a/content/common/features.gni
+++ b/content/common/features.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/features.gni")
 
 declare_args() {
diff --git a/content/common/features.h b/content/common/features.h
index 0d2aae03..f781ece 100644
--- a/content/common/features.h
+++ b/content/common/features.h
@@ -35,13 +35,11 @@
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kDeviceMonitorMac);
 #endif
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kDocumentPolicyNegotiation);
-CONTENT_EXPORT BASE_DECLARE_FEATURE(kEnumerateDevicesHideDeviceIDs);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kEnableBackForwardCacheForScreenReader);
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kEnableDevToolsJsErrorReporting);
 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kEnsureAllowBindingsIsAlwaysForWebUI);
-CONTENT_EXPORT BASE_DECLARE_FEATURE(kEnumerateDevicesHideDeviceIDs);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kEmbeddingRequiresOptIn);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kExperimentalContentSecurityPolicyFeatures);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kFedCmIdAssertionCORS);
diff --git a/content/common/gin_java_bridge.mojom b/content/common/gin_java_bridge.mojom
index cf97777e..ff803b2b 100644
--- a/content/common/gin_java_bridge.mojom
+++ b/content/common/gin_java_bridge.mojom
@@ -4,6 +4,8 @@
 
 module content.mojom;
 
+import "mojo/public/mojom/base/values.mojom";
+
 // Descriptive errors raised by the gin java bridge.
 enum GinJavaBridgeError {
   kGinJavaBridgeNoError,
@@ -15,3 +17,70 @@
   kGinJavaBridgeNonAssignableTypes,
   kGinJavaBridgeRenderFrameDeleted,
 };
+
+// Interface for adding objects to a frame in the renderer.
+// TODO(crbug.com/794320): This interface mirrors
+// `blink.mojom.RemoteObjectGateway` and should be removed once
+// crbug.com/794320 is complete.
+interface GinJavaBridge {
+  // Sent from browser to renderer to add a Java object with the given name.
+  // Object IDs are generated on the browser side.
+  AddNamedObject(string name, int32 object_id);
+
+  // Sent from browser to renderer to remove a Java object with the given name.
+  RemoveNamedObject(string name);
+};
+
+// Implemented in the process hosting the remote object. Allows methods to be
+// synchronously invoked on the object.
+// TODO(crbug.com/794320): This interface mirrors `blink.mojom.RemoteObject`
+// but without the serialization changes. This should be merged with that
+// definition once crbug.com/794320 is complete.
+interface GinJavaBridgeRemoteObject {
+  // Sent from renderer to browser to get information about methods of
+  // the given object. The query will only succeed if inspection of injected
+  // objects is enabled on the browser side.
+  [Sync]
+  GetMethods() => (array<string> method_names);
+
+  // Sent from renderer to browser to find out, if an object has a method with
+  // the given name.
+  [Sync]
+  HasMethod(string method_name) => (bool result);
+
+  // Sent from renderer to browser to invoke a method. Method arguments
+  // are chained into |arguments| list. base::Value::List is used for |result|
+  // as a container to work around immutability of base::Value.
+  // Empty result list indicates that an error has happened on the Java side
+  // (either bridge-induced error or an unhandled Java exception) and an
+  // exception must be thrown into JavaScript. |error_code| indicates the cause
+  // of the error.
+  // Some special value types that are not supported by base::Value are encoded
+  // as BinaryValues via GinJavaBridgeValue.
+  [Sync]
+  InvokeMethod(string method_name, mojo_base.mojom.ListValue arguments) =>
+    (GinJavaBridgeError error_code, mojo_base.mojom.ListValue result);
+};
+
+// Implemented in the process hosting the remote objects. Allows access to an
+// object graph.
+// TODO(crbug.com/794320): This class mirrors `blink.mojom.RemoteObjectHost`
+// and should be removed once crbug.com/794320 is complete.
+interface GinJavaBridgeHost {
+  // Binds |receiver| to an implementation of RemoteObject corresponding to
+  // |object_id|.
+  GetObject(int32 object_id,
+            pending_receiver<GinJavaBridgeRemoteObject> receiver);
+
+  // Sent from renderer to browser in two cases:
+  //
+  //  1. (Main usage) To inform that the JS wrapper of the object has
+  //     been completely dereferenced and garbage-collected.
+  //
+  //  2. To notify the browser that wrapper creation has failed.  The browser
+  //     side assumes optimistically that every time an object is returned from
+  //     a method, the corresponding wrapper object will be successfully
+  //     created on the renderer side. Sending of this message informs the
+  //     browser whether this expectation has failed.
+  ObjectWrapperDeleted(int32 object_id);
+};
diff --git a/content/common/gin_java_bridge_messages.h b/content/common/gin_java_bridge_messages.h
index 8986bcb..67882e7 100644
--- a/content/common/gin_java_bridge_messages.h
+++ b/content/common/gin_java_bridge_messages.h
@@ -38,7 +38,7 @@
 // objects is enabled on the browser side.
 IPC_SYNC_MESSAGE_ROUTED1_1(GinJavaBridgeHostMsg_GetMethods,
                            int32_t /* object_id */,
-                           std::set<std::string> /* returned_method_names */)
+                           std::vector<std::string> /* returned_method_names */)
 
 // Sent from renderer to browser to find out, if an object has a method with
 // the given name.
diff --git a/content/gpu/BUILD.gn b/content/gpu/BUILD.gn
index 93559f6..a20f5d7 100644
--- a/content/gpu/BUILD.gn
+++ b/content/gpu/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/ui.gni")
 import("//gpu/vulkan/features.gni")
diff --git a/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java b/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java
index 5a8ce826..b79cbf0 100644
--- a/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java
+++ b/content/public/android/java/src/org/chromium/content/browser/AttributionOsLevelManager.java
@@ -112,7 +112,12 @@
         if (!supportsAttribution()) {
             return null;
         }
-        mManager = MeasurementManagerFutures.from(ContextUtils.getApplicationContext());
+        try {
+            mManager = MeasurementManagerFutures.from(ContextUtils.getApplicationContext());
+        } catch (Throwable t) {
+            // An error may be thrown if android.ext.adservices is not loaded.
+            Log.i(TAG, "Failed to get measurement manager", t);
+        }
         return mManager;
     }
 
@@ -394,8 +399,14 @@
             AttributionOsLevelManagerJni.get().onMeasurementStateReturned(0);
             return;
         }
-        MeasurementManagerFutures mm =
-                MeasurementManagerFutures.from(ContextUtils.getApplicationContext());
+        MeasurementManagerFutures mm = null;
+        try {
+            mm = MeasurementManagerFutures.from(ContextUtils.getApplicationContext());
+        } catch (Throwable t) {
+            // An error may be thrown if android.ext.adservices is not loaded.
+            Log.i(TAG, "Failed to get measurement manager", t);
+        }
+
         if (mm == null) {
             AttributionOsLevelManagerJni.get().onMeasurementStateReturned(0);
             return;
diff --git a/content/public/browser/federated_identity_permission_context_delegate.h b/content/public/browser/federated_identity_permission_context_delegate.h
index 37a72abf..98510c1 100644
--- a/content/public/browser/federated_identity_permission_context_delegate.h
+++ b/content/public/browser/federated_identity_permission_context_delegate.h
@@ -40,25 +40,6 @@
   virtual void RemoveIdpSigninStatusObserver(
       IdpSigninStatusObserver* observer) = 0;
 
-  // Determine whether the `relying_party_requester` has an existing active
-  // session for the specified `account_identifier` with the
-  // `identity_provider`.
-  virtual bool HasActiveSession(const url::Origin& relying_party_requester,
-                                const url::Origin& identity_provider,
-                                const std::string& account_identifier) = 0;
-
-  // Grant active session capabilities between the `relying_party_requester` and
-  // `identity_provider` origins for the specified account.
-  virtual void GrantActiveSession(const url::Origin& relying_party_requester,
-                                  const url::Origin& identity_provider,
-                                  const std::string& account_identifier) = 0;
-
-  // Revoke a previously-provided grant from the `relying_party_requester` to
-  // the `identity_provider` for the specified account.
-  virtual void RevokeActiveSession(const url::Origin& relying_party_requester,
-                                   const url::Origin& identity_provider,
-                                   const std::string& account_identifier) = 0;
-
   // Determine whether there is an existing permission grant to share identity
   // information for the given account to the `relying_party_requester` when
   // embedded in `relying_party_embedder`. `account_id` can be omitted to
diff --git a/content/public/browser/identity_request_dialog_controller.cc b/content/public/browser/identity_request_dialog_controller.cc
index 752fa739..3e7a23cf 100644
--- a/content/public/browser/identity_request_dialog_controller.cc
+++ b/content/public/browser/identity_request_dialog_controller.cc
@@ -60,6 +60,7 @@
     IdentityRequestAccount::SignInMode sign_in_mode,
     bool show_auto_reauthn_checkbox,
     AccountSelectionCallback on_selected,
+    SigninToIdPCallback on_add_account,
     DismissCallback dismiss_callback) {
   if (!is_interception_enabled_) {
     std::move(dismiss_callback).Run(DismissReason::kOther);
diff --git a/content/public/browser/identity_request_dialog_controller.h b/content/public/browser/identity_request_dialog_controller.h
index 8f8ad17..4ce3ec06 100644
--- a/content/public/browser/identity_request_dialog_controller.h
+++ b/content/public/browser/identity_request_dialog_controller.h
@@ -131,6 +131,7 @@
       IdentityRequestAccount::SignInMode sign_in_mode,
       bool show_auto_reauthn_checkbox,
       AccountSelectionCallback on_selected,
+      SigninToIdPCallback on_add_account,
       DismissCallback dismiss_callback);
 
   // Shows a failure UI when the accounts fetch is failed such that it is
diff --git a/content/public/browser/navigation_handle.h b/content/public/browser/navigation_handle.h
index 13c3926..971ed19a 100644
--- a/content/public/browser/navigation_handle.h
+++ b/content/public/browser/navigation_handle.h
@@ -48,7 +48,6 @@
 namespace net {
 class HttpRequestHeaders;
 class HttpResponseHeaders;
-class ProxyServer;
 }  // namespace net
 
 namespace perfetto::protos::pbzero {
@@ -480,9 +479,6 @@
   // Returns true if the navigation response was cached.
   virtual bool WasResponseCached() = 0;
 
-  // Returns the proxy server used for this navigation, if any.
-  virtual const net::ProxyServer& GetProxyServer() = 0;
-
   // Returns the value of the hrefTranslate attribute if this navigation was
   // initiated from a link that had that attribute set.
   virtual const std::string& GetHrefTranslate() = 0;
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn
index b52f747..caa3ef1 100644
--- a/content/public/common/BUILD.gn
+++ b/content/public/common/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 60446350..9297cf62 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -377,11 +377,6 @@
              "FedCmIdPregistration",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Enables usage of the FedCM logoutRPs method.
-BASE_FEATURE(kFedCmLogoutRps,
-             "FedCmLogoutRps",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 // Enables usage of the FedCM API with metrics endpoint at the same time.
 BASE_FEATURE(kFedCmMetricsEndpoint,
              "FedCmMetricsEndpoint",
@@ -1249,6 +1244,11 @@
              "AutoDisableAccessibilityV2",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Enables the mojo based gin java bridge implementation.
+BASE_FEATURE(kGinJavaBridgeMojo,
+             "GinJavaBridgeMojo",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // Reduce the priority of GPU process when in background so it is more likely
 // to be killed first if the OS needs more memory.
 BASE_FEATURE(kReduceGpuPriorityOnBackground,
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 2159c30..8ea86ae 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -96,7 +96,6 @@
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kFedCmError);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kFedCmDomainHint);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kFedCmIdPRegistration);
-CONTENT_EXPORT BASE_DECLARE_FEATURE(kFedCmLogoutRps);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kFedCmMetricsEndpoint);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kFedCmMultipleIdentityProviders);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kFedCmRevoke);
@@ -309,6 +308,7 @@
     kAccessibilityPageZoomOSLevelAdjustment;
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kAccessibilityPerformanceTesting);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kAutoDisableAccessibilityV2);
+CONTENT_EXPORT BASE_DECLARE_FEATURE(kGinJavaBridgeMojo);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kReduceGpuPriorityOnBackground);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kMouseAndTrackpadDropdownMenu);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kRequestDesktopSiteAdditions);
diff --git a/content/public/test/mock_navigation_handle.cc b/content/public/test/mock_navigation_handle.cc
index 733a2946..dd6c551a 100644
--- a/content/public/test/mock_navigation_handle.cc
+++ b/content/public/test/mock_navigation_handle.cc
@@ -18,7 +18,6 @@
 
 MockNavigationHandle::MockNavigationHandle(WebContents* web_contents)
     : navigation_id_(++g_mock_handle_id), web_contents_(web_contents) {
-  proxy_server_ = net::ProxyServer::Direct();
 }
 
 MockNavigationHandle::MockNavigationHandle(const GURL& url,
@@ -31,7 +30,6 @@
                                     ? render_frame_host_->IsInPrimaryMainFrame()
                                     : true) {
   redirect_chain_.push_back(url);
-  proxy_server_ = net::ProxyServer::Direct();
   runtime_feature_state_context_ = blink::RuntimeFeatureStateContext();
 }
 
diff --git a/content/public/test/mock_navigation_handle.h b/content/public/test/mock_navigation_handle.h
index 8db36c6..281732ca 100644
--- a/content/public/test/mock_navigation_handle.h
+++ b/content/public/test/mock_navigation_handle.h
@@ -176,7 +176,6 @@
   MOCK_METHOD0(IsSignedExchangeInnerResponse, bool());
   MOCK_METHOD0(HasPrefetchedAlternativeSubresourceSignedExchange, bool());
   bool WasResponseCached() override { return was_response_cached_; }
-  const net::ProxyServer& GetProxyServer() override { return proxy_server_; }
   const std::string& GetHrefTranslate() override { return href_translate_; }
   const absl::optional<blink::Impression>& GetImpression() override {
     return impression_;
@@ -314,9 +313,6 @@
   void set_was_response_cached(bool was_response_cached) {
     was_response_cached_ = was_response_cached;
   }
-  void set_proxy_server(const net::ProxyServer& proxy_server) {
-    proxy_server_ = proxy_server;
-  }
   void set_impression(const blink::Impression& impression) {
     impression_ = impression;
   }
@@ -364,7 +360,6 @@
   content::GlobalRequestID global_request_id_;
   bool is_form_submission_ = false;
   bool was_response_cached_ = false;
-  net::ProxyServer proxy_server_;
   absl::optional<url::Origin> initiator_origin_;
   absl::optional<GURL> initiator_base_url_;
   ReloadType reload_type_ = content::ReloadType::NONE;
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 697fa7c..19a8585 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc
index d60538d..afdb5ff 100644
--- a/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -723,8 +723,6 @@
   // the document.
   weak_factory_for_serialization_pipeline_.InvalidateWeakPtrs();
 
-  last_serialization_timestamp_ = now;
-
   SendPendingAccessibilityEvents();
 }
 
@@ -1425,6 +1423,7 @@
   // AXReadyCallback() will be called. ScheduleAXUpdate() will only schedule a
   // visual update if the AXObjectCache is dirty.
   serialization_in_flight_ = false;
+  last_serialization_timestamp_ = base::Time::Now();
   if (immediate_update_required_after_ack_) {
     ScheduleImmediateAXUpdate();
     immediate_update_required_after_ack_ = false;
diff --git a/content/renderer/accessibility/render_accessibility_impl.h b/content/renderer/accessibility/render_accessibility_impl.h
index 4b05f9d..9387c9c 100644
--- a/content/renderer/accessibility/render_accessibility_impl.h
+++ b/content/renderer/accessibility/render_accessibility_impl.h
@@ -328,14 +328,15 @@
   };
   LoadingStage loading_stage_ = LoadingStage::kPreload;
 
-  // This stores the last time during that a serialization was done, so that
-  // serializations can be skipped if the time since the last serialization is
-  // less than GetDeferredEventsDelay(). Setting to "beginning of time" causes
-  // the upcoming serialization to occur at the next available opportunity.
-  // Batching is used to reduce the number of serializations, in order to
-  // provide overall faster content updates while using less CPU, because nodes
-  // that change multiple times in a short time period only need to be
-  // serialized once, e.g. during page loads or animations.
+  // This stores the last time a serialization was ACK'ed after being sent to
+  // the browser, so that serializations can be skipped if the time since the
+  // last serialization is less than GetDeferredEventsDelay(). Setting to
+  // "beginning of time" causes the upcoming serialization to occur at the next
+  // available opportunity.  Batching is used to reduce the number of
+  // serializations, in order to provide overall faster content updates while
+  // using less CPU, because nodes that change multiple times in a short time
+  // period only need to be serialized once, e.g. during page loads or
+  // animations.
   static constexpr base::Time kSerializeAtNextOpportunity =
       base::Time::UnixEpoch();
   base::Time last_serialization_timestamp_ = kSerializeAtNextOpportunity;
diff --git a/content/renderer/java/gin_java_bridge_dispatcher.cc b/content/renderer/java/gin_java_bridge_dispatcher.cc
index 7323b79..16288c1 100644
--- a/content/renderer/java/gin_java_bridge_dispatcher.cc
+++ b/content/renderer/java/gin_java_bridge_dispatcher.cc
@@ -9,8 +9,10 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/common/gin_java_bridge_messages.h"
+#include "content/public/common/content_features.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/renderer/java/gin_java_bridge_object.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_view.h"
 
@@ -18,17 +20,23 @@
 
 GinJavaBridgeDispatcher::GinJavaBridgeDispatcher(RenderFrame* render_frame)
     : RenderFrameObserver(render_frame),
-      inside_did_clear_window_object_(false) {
+      enable_mojo_(base::FeatureList::IsEnabled(features::kGinJavaBridgeMojo)) {
+  if (enable_mojo_) {
+    render_frame->GetBrowserInterfaceBroker()->GetInterface(
+        remote_.BindNewPipeAndPassReceiver());
+  }
 }
 
-GinJavaBridgeDispatcher::~GinJavaBridgeDispatcher() {
-}
+GinJavaBridgeDispatcher::~GinJavaBridgeDispatcher() = default;
 
 bool GinJavaBridgeDispatcher::OnMessageReceived(const IPC::Message& msg) {
+  if (enable_mojo_) {
+    return false;
+  }
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(GinJavaBridgeDispatcher, msg)
-    IPC_MESSAGE_HANDLER(GinJavaBridgeMsg_AddNamedObject, OnAddNamedObject)
-    IPC_MESSAGE_HANDLER(GinJavaBridgeMsg_RemoveNamedObject, OnRemoveNamedObject)
+    IPC_MESSAGE_HANDLER(GinJavaBridgeMsg_AddNamedObject, AddNamedObject)
+    IPC_MESSAGE_HANDLER(GinJavaBridgeMsg_RemoveNamedObject, RemoveNamedObject)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -51,9 +59,12 @@
     if (objects_.Lookup(iter->second))
       objects_.Remove(iter->second);
     GinJavaBridgeObject* object = GinJavaBridgeObject::InjectNamed(
-        render_frame()->GetWebFrame(), AsWeakPtr(), iter->first, iter->second);
+        render_frame()->GetWebFrame(), AsWeakPtr(), iter->first, iter->second,
+        enable_mojo_);
     if (object) {
       objects_.AddWithID(object, iter->second);
+    } else if (enable_mojo_) {
+      remote_->ObjectWrapperDeleted(iter->second);
     } else {
       // Inform the host about wrapper creation failure.
       render_frame()->Send(new GinJavaBridgeHostMsg_ObjectWrapperDeleted(
@@ -62,15 +73,14 @@
   }
 }
 
-void GinJavaBridgeDispatcher::OnAddNamedObject(
-    const std::string& name,
-    ObjectID object_id) {
+void GinJavaBridgeDispatcher::AddNamedObject(const std::string& name,
+                                             ObjectID object_id) {
   // Added objects only become available after page reload, so here they
   // are only added into the internal map.
   named_objects_.insert(std::make_pair(name, object_id));
 }
 
-void GinJavaBridgeDispatcher::OnRemoveNamedObject(const std::string& name) {
+void GinJavaBridgeDispatcher::RemoveNamedObject(const std::string& name) {
   // Removal becomes in effect on next reload. We simply removing the entry
   // from the map here.
   DCHECK(base::Contains(named_objects_, name));
@@ -79,14 +89,16 @@
 
 void GinJavaBridgeDispatcher::GetJavaMethods(
     ObjectID object_id,
-    std::set<std::string>* methods) {
-  render_frame()->Send(new GinJavaBridgeHostMsg_GetMethods(
-      routing_id(), object_id, methods));
+    std::vector<std::string>* methods) {
+  CHECK(!enable_mojo_);
+  render_frame()->Send(
+      new GinJavaBridgeHostMsg_GetMethods(routing_id(), object_id, methods));
 }
 
 bool GinJavaBridgeDispatcher::HasJavaMethod(ObjectID object_id,
                                             const std::string& method_name) {
   bool result;
+  CHECK(!enable_mojo_);
   render_frame()->Send(new GinJavaBridgeHostMsg_HasMethod(
       routing_id(), object_id, method_name, &result));
   return result;
@@ -98,13 +110,9 @@
     base::Value::List arguments,
     mojom::GinJavaBridgeError* error) {
   base::Value::List result_wrapper;
-  render_frame()->Send(
-      new GinJavaBridgeHostMsg_InvokeMethod(routing_id(),
-                                            object_id,
-                                            method_name,
-                                            arguments,
-                                            &result_wrapper,
-                                            error));
+  CHECK(!enable_mojo_);
+  render_frame()->Send(new GinJavaBridgeHostMsg_InvokeMethod(
+      routing_id(), object_id, method_name, arguments, &result_wrapper, error));
   if (result_wrapper.empty())
     return nullptr;
   return base::Value::ToUniquePtrValue(result_wrapper[0].Clone());
@@ -113,8 +121,8 @@
 GinJavaBridgeObject* GinJavaBridgeDispatcher::GetObject(ObjectID object_id) {
   GinJavaBridgeObject* result = objects_.Lookup(object_id);
   if (!result) {
-    result = GinJavaBridgeObject::InjectAnonymous(render_frame()->GetWebFrame(),
-                                                  AsWeakPtr(), object_id);
+    result = GinJavaBridgeObject::InjectAnonymous(
+        render_frame()->GetWebFrame(), AsWeakPtr(), object_id, enable_mojo_);
     if (result)
       objects_.AddWithID(result, object_id);
   }
@@ -127,12 +135,25 @@
   // Ignore cleaning up of old object wrappers.
   if (objects_.Lookup(object_id) != object) return;
   objects_.Remove(object_id);
-  render_frame()->Send(
-      new GinJavaBridgeHostMsg_ObjectWrapperDeleted(routing_id(), object_id));
+
+  if (enable_mojo_) {
+    remote_->ObjectWrapperDeleted(object_id);
+  } else {
+    render_frame()->Send(
+        new GinJavaBridgeHostMsg_ObjectWrapperDeleted(routing_id(), object_id));
+  }
 }
 
 void GinJavaBridgeDispatcher::OnDestruct() {
+  // This is a self owned receiver when mojo is used.
+  if (enable_mojo_) {
+    return;
+  }
   delete this;
 }
 
+mojom::GinJavaBridgeHost* GinJavaBridgeDispatcher::GetRemoteObjectHost() {
+  return remote_.get();
+}
+
 }  // namespace content
diff --git a/content/renderer/java/gin_java_bridge_dispatcher.h b/content/renderer/java/gin_java_bridge_dispatcher.h
index 095b694..4081ca2 100644
--- a/content/renderer/java/gin_java_bridge_dispatcher.h
+++ b/content/renderer/java/gin_java_bridge_dispatcher.h
@@ -10,10 +10,15 @@
 #include <set>
 
 #include "base/containers/id_map.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "content/common/android/gin_java_bridge_errors.h"
+#include "content/common/gin_java_bridge.mojom.h"
 #include "content/public/renderer/render_frame_observer.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace content {
 
@@ -27,6 +32,7 @@
 // again.
 class GinJavaBridgeDispatcher
     : public base::SupportsWeakPtr<GinJavaBridgeDispatcher>,
+      public mojom::GinJavaBridge,
       public RenderFrameObserver {
  public:
   // GinJavaBridgeObjects are managed by gin. An object gets destroyed
@@ -47,7 +53,8 @@
   bool OnMessageReceived(const IPC::Message& message) override;
   void DidClearWindowObject() override;
 
-  void GetJavaMethods(ObjectID object_id, std::set<std::string>* methods);
+  void GetJavaMethods(ObjectID object_id, std::vector<std::string>* methods);
+
   bool HasJavaMethod(ObjectID object_id, const std::string& method_name);
   std::unique_ptr<base::Value> InvokeJavaMethod(
       ObjectID object_id,
@@ -57,18 +64,22 @@
   GinJavaBridgeObject* GetObject(ObjectID object_id);
   void OnGinJavaBridgeObjectDeleted(GinJavaBridgeObject* object);
 
+  void AddNamedObject(const std::string& name, ObjectID object_id) override;
+  void RemoveNamedObject(const std::string& name) override;
+
+  mojom::GinJavaBridgeHost* GetRemoteObjectHost();
+
  private:
   // RenderFrameObserver implementation.
   void OnDestruct() override;
 
-  void OnAddNamedObject(const std::string& name,
-                        ObjectID object_id);
-  void OnRemoveNamedObject(const std::string& name);
-
   typedef std::map<std::string, ObjectID> NamedObjectMap;
   NamedObjectMap named_objects_;
   ObjectMap objects_;
-  bool inside_did_clear_window_object_;
+  bool inside_did_clear_window_object_ = false;
+  const bool enable_mojo_;
+
+  mojo::Remote<mojom::GinJavaBridgeHost> remote_;
 };
 
 }  // namespace content
diff --git a/content/renderer/java/gin_java_bridge_object.cc b/content/renderer/java/gin_java_bridge_object.cc
index 48fecea2..52346a6 100644
--- a/content/renderer/java/gin_java_bridge_object.cc
+++ b/content/renderer/java/gin_java_bridge_object.cc
@@ -7,6 +7,7 @@
 #include "base/containers/contains.h"
 #include "base/functional/bind.h"
 #include "content/common/gin_java_bridge_messages.h"
+#include "content/public/common/content_features.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/renderer/java/gin_java_function_invocation_helper.h"
 #include "gin/function_template.h"
@@ -21,7 +22,8 @@
     blink::WebLocalFrame* frame,
     const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
     const std::string& object_name,
-    GinJavaBridgeDispatcher::ObjectID object_id) {
+    GinJavaBridgeDispatcher::ObjectID object_id,
+    bool mojo_enabled) {
   v8::Isolate* isolate = frame->GetAgentGroupScheduler()->Isolate();
   v8::HandleScope handle_scope(isolate);
   v8::Local<v8::Context> context = frame->MainWorldScriptContext();
@@ -29,7 +31,7 @@
     return NULL;
 
   GinJavaBridgeObject* object =
-      new GinJavaBridgeObject(isolate, dispatcher, object_id);
+      new GinJavaBridgeObject(isolate, dispatcher, object_id, mojo_enabled);
 
   v8::Context::Scope context_scope(context);
   v8::Local<v8::Object> global = context->Global();
@@ -50,31 +52,42 @@
 GinJavaBridgeObject* GinJavaBridgeObject::InjectAnonymous(
     blink::WebLocalFrame* frame,
     const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
-    GinJavaBridgeDispatcher::ObjectID object_id) {
+    GinJavaBridgeDispatcher::ObjectID object_id,
+    bool mojo_enabled) {
   return new GinJavaBridgeObject(frame->GetAgentGroupScheduler()->Isolate(),
-                                 dispatcher, object_id);
+                                 dispatcher, object_id, mojo_enabled);
 }
 
 GinJavaBridgeObject::GinJavaBridgeObject(
     v8::Isolate* isolate,
     const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
-    GinJavaBridgeDispatcher::ObjectID object_id)
+    GinJavaBridgeDispatcher::ObjectID object_id,
+    bool mojo_enabled)
     : gin::NamedPropertyInterceptor(isolate, this),
       dispatcher_(dispatcher),
       object_id_(object_id),
       frame_routing_id_(dispatcher_->routing_id()),
       template_cache_(isolate) {
+  if (mojo_enabled) {
+    dispatcher_->GetRemoteObjectHost()->GetObject(
+        object_id, remote_.BindNewPipeAndPassReceiver());
+  }
 }
 
 GinJavaBridgeObject::~GinJavaBridgeObject() {
   if (dispatcher_) {
     dispatcher_->OnGinJavaBridgeObjectDeleted(this);
   } else {
-    // A wrapper can outlive a render frame, and thus the dispatcher.
-    // Note that we intercept GinJavaBridgeHostMsg messages in a browser filter
-    // thus it's OK to send the message with a routing id of a ceased frame.
-    RenderThread::Get()->Send(new GinJavaBridgeHostMsg_ObjectWrapperDeleted(
-        frame_routing_id_, object_id_));
+    // For the mojo case the browser will see the remote is disconnected.
+    if (!remote_) {
+      CHECK(!base::FeatureList::IsEnabled(features::kGinJavaBridgeMojo));
+      // A wrapper can outlive a render frame, and thus the dispatcher.
+      // Note that we intercept GinJavaBridgeHostMsg messages in a browser
+      // filter thus it's OK to send the message with a routing id of a ceased
+      // frame.
+      RenderThread::Get()->Send(new GinJavaBridgeHostMsg_ObjectWrapperDeleted(
+          frame_routing_id_, object_id_));
+    }
   }
 }
 
@@ -91,7 +104,14 @@
     if (!dispatcher_) {
       return v8::Local<v8::Value>();
     }
-    known_methods_[property] = dispatcher_->HasJavaMethod(object_id_, property);
+    if (remote_) {
+      bool result = false;
+      remote_->HasMethod(property, &result);
+      known_methods_[property] = result;
+    } else {
+      known_methods_[property] =
+          dispatcher_->HasJavaMethod(object_id_, property);
+    }
   }
   if (known_methods_[property]) {
     return GetFunctionTemplate(isolate, property)
@@ -104,10 +124,13 @@
 
 std::vector<std::string> GinJavaBridgeObject::EnumerateNamedProperties(
     v8::Isolate* isolate) {
-  std::set<std::string> method_names;
-  if (dispatcher_)
+  std::vector<std::string> method_names;
+  if (remote_) {
+    remote_->GetMethods(&method_names);
+  } else if (dispatcher_) {
     dispatcher_->GetJavaMethods(object_id_, &method_names);
-  return std::vector<std::string> (method_names.begin(), method_names.end());
+  }
+  return method_names;
 }
 
 v8::Local<v8::FunctionTemplate> GinJavaBridgeObject::GetFunctionTemplate(
@@ -125,6 +148,14 @@
   return function_template;
 }
 
+mojom::GinJavaBridgeRemoteObject* GinJavaBridgeObject::GetRemote() {
+  if (!remote_) {
+    // non-mojo case.
+    return nullptr;
+  }
+  return remote_.get();
+}
+
 gin::WrapperInfo GinJavaBridgeObject::kWrapperInfo = {gin::kEmbedderNativeGin};
 
 }  // namespace content
diff --git a/content/renderer/java/gin_java_bridge_object.h b/content/renderer/java/gin_java_bridge_object.h
index f9032c6..6309a1d 100644
--- a/content/renderer/java/gin_java_bridge_object.h
+++ b/content/renderer/java/gin_java_bridge_object.h
@@ -8,11 +8,13 @@
 #include <map>
 
 #include "base/memory/weak_ptr.h"
+#include "content/common/gin_java_bridge.mojom.h"
 #include "content/renderer/java/gin_java_bridge_dispatcher.h"
 #include "gin/handle.h"
 #include "gin/interceptor.h"
 #include "gin/object_template_builder.h"
 #include "gin/wrappable.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "v8/include/v8-util.h"
 
 namespace blink {
@@ -45,16 +47,22 @@
       blink::WebLocalFrame* frame,
       const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
       const std::string& object_name,
-      GinJavaBridgeDispatcher::ObjectID object_id);
+      GinJavaBridgeDispatcher::ObjectID object_id,
+      bool mojo_enabled);
   static GinJavaBridgeObject* InjectAnonymous(
       blink::WebLocalFrame* frame,
       const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
-      GinJavaBridgeDispatcher::ObjectID object_id);
+      GinJavaBridgeDispatcher::ObjectID object_id,
+      bool mojo_enabled);
+
+  // Returns the bound remote object, nullptr if mojo is disabled.
+  mojom::GinJavaBridgeRemoteObject* GetRemote();
 
  private:
   GinJavaBridgeObject(v8::Isolate* isolate,
                       const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher,
-                      GinJavaBridgeDispatcher::ObjectID object_id);
+                      GinJavaBridgeDispatcher::ObjectID object_id,
+                      bool mojo_enabled);
   ~GinJavaBridgeObject() override;
 
   v8::Local<v8::FunctionTemplate> GetFunctionTemplate(v8::Isolate* isolate,
@@ -65,6 +73,7 @@
   int frame_routing_id_;
   std::map<std::string, bool> known_methods_;
   v8::StdGlobalValueMap<std::string, v8::FunctionTemplate> template_cache_;
+  mojo::Remote<mojom::GinJavaBridgeRemoteObject> remote_;
 };
 
 }  // namespace content
diff --git a/content/renderer/java/gin_java_function_invocation_helper.cc b/content/renderer/java/gin_java_function_invocation_helper.cc
index 72b52587..6175e38d 100644
--- a/content/renderer/java/gin_java_function_invocation_helper.cc
+++ b/content/renderer/java/gin_java_function_invocation_helper.cc
@@ -32,8 +32,7 @@
     const base::WeakPtr<GinJavaBridgeDispatcher>& dispatcher)
     : method_name_(method_name),
       dispatcher_(dispatcher),
-      converter_(new GinJavaBridgeValueConverter()) {
-}
+      converter_(new GinJavaBridgeValueConverter()) {}
 
 GinJavaFunctionInvocationHelper::~GinJavaFunctionInvocationHelper() {
 }
@@ -75,8 +74,19 @@
   }
 
   mojom::GinJavaBridgeError error;
-  std::unique_ptr<base::Value> result = dispatcher_->InvokeJavaMethod(
-      object->object_id(), method_name_, std::move(arguments), &error);
+
+  std::unique_ptr<base::Value> result;
+  if (auto* remote = object->GetRemote()) {
+    base::Value::List result_wrapper;
+    remote->InvokeMethod(method_name_, std::move(arguments), &error,
+                         &result_wrapper);
+    if (!result_wrapper.empty()) {
+      result = base::Value::ToUniquePtrValue(result_wrapper[0].Clone());
+    }
+  } else {
+    result = dispatcher_->InvokeJavaMethod(object->object_id(), method_name_,
+                                           std::move(arguments), &error);
+  }
   if (!result.get()) {
     args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
         args->isolate(), GinJavaBridgeErrorToString(error))));
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index be58aba..4d902f79 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -259,6 +259,7 @@
 #include <cpu-features.h>
 
 #include "content/renderer/java/gin_java_bridge_dispatcher.h"
+#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
 #endif
 
 using base::Time;
@@ -1963,7 +1964,9 @@
   // Everything below subclasses RenderFrameObserver and is automatically
   // deleted when the RenderFrame gets deleted.
 #if BUILDFLAG(IS_ANDROID)
-  new GinJavaBridgeDispatcher(this);
+  if (!base::FeatureList::IsEnabled(features::kGinJavaBridgeMojo)) {
+    new GinJavaBridgeDispatcher(this);
+  }
 #endif
 }
 
@@ -6129,8 +6132,24 @@
       ->AddInterface<blink::mojom::RenderAccessibility>(base::BindRepeating(
           &RenderAccessibilityManager::BindReceiver,
           base::Unretained(render_accessibility_manager_.get())));
+
+#if BUILDFLAG(IS_ANDROID)
+  if (base::FeatureList::IsEnabled(features::kGinJavaBridgeMojo)) {
+    GetAssociatedInterfaceRegistry()->AddInterface<mojom::GinJavaBridge>(
+        base::BindRepeating(&RenderFrameImpl::BindGinJavaBridge,
+                            weak_factory_.GetWeakPtr()));
+  }
+#endif
 }
 
+#if BUILDFLAG(IS_ANDROID)
+void RenderFrameImpl::BindGinJavaBridge(
+    mojo::PendingAssociatedReceiver<mojom::GinJavaBridge> receiver) {
+  mojo::MakeSelfOwnedAssociatedReceiver(
+      std::make_unique<GinJavaBridgeDispatcher>(this), std::move(receiver));
+}
+#endif
+
 void RenderFrameImpl::BindMhtmlFileWriter(
     mojo::PendingAssociatedReceiver<mojom::MhtmlFileWriter> receiver) {
   mhtml_file_writer_receiver_.reset();
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 7a49bed6..2a675b88 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -121,6 +121,10 @@
 #include "content/common/pepper_plugin.mojom.h"
 #endif
 
+#if BUILDFLAG(IS_ANDROID)
+#include "content/common/gin_java_bridge.mojom.h"
+#endif
+
 namespace blink {
 namespace scheduler {
 class WebAgentGroupScheduler;
@@ -702,6 +706,11 @@
   void BindMhtmlFileWriter(
       mojo::PendingAssociatedReceiver<mojom::MhtmlFileWriter> receiver);
 
+#if BUILDFLAG(IS_ANDROID)
+  void BindGinJavaBridge(
+      mojo::PendingAssociatedReceiver<mojom::GinJavaBridge> receiver);
+#endif
+
   // Binds to the autoplay configuration service in the browser.
   void BindAutoplayConfiguration(
       mojo::PendingAssociatedReceiver<blink::mojom::AutoplayConfigurationClient>
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc
index 3825fd0a..db6b9397 100644
--- a/content/renderer/render_frame_impl_browsertest.cc
+++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -56,6 +56,7 @@
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/public/test/test_web_frame_content_dumper.h"
 #include "third_party/blink/public/web/web_frame_widget.h"
 #include "third_party/blink/public/web/web_history_item.h"
 #include "third_party/blink/public/web/web_local_frame.h"
@@ -1122,4 +1123,105 @@
   EXPECT_FALSE(main_frame->delayed_state_sync_timer_.IsRunning());
 }
 
+namespace {
+
+// All content setting tests use the same data url, which contains html which
+// has different behavior depending on whether script is enabled or disabled.
+blink::mojom::CommonNavigationParamsPtr
+GetCommonParamsForContentSettingsTest() {
+  const char kHtml[] =
+      "<html>"
+      "<noscript>JS_DISABLED</noscript>"
+      "<script>document.write('JS_ENABLED');</script>"
+      "</html>";
+  std::string data_url_contents = "data:text/html,";
+  data_url_contents += kHtml;
+
+  auto common_params = blink::CreateCommonNavigationParams();
+  common_params->url = GURL(data_url_contents);
+  return common_params;
+}
+
+// Dump the layout tree and see whether it contains "text".
+bool HasText(blink::WebLocalFrame* frame, const std::string& text) {
+  std::string layout_tree =
+      blink::TestWebFrameContentDumper::DumpLayoutTreeAsText(
+          frame, blink::TestWebFrameContentDumper::kLayoutAsTextNormal)
+          .Utf8();
+
+  return base::Contains(layout_tree, text);
+}
+
+// Waits for the navigation to finish.
+void NavigateAndWait(content::TestRenderFrame* frame,
+                     blink::mojom::CommonNavigationParamsPtr common_params,
+                     blink::mojom::CommitNavigationParamsPtr commit_params,
+                     blink::WebView* web_view) {
+  FrameLoadWaiter waiter(frame);
+  frame->Navigate(std::move(common_params), std::move(commit_params));
+  waiter.Wait();
+}
+
+}  // namespace
+
+// Regression test for crbug.com/232410: Load a page with JS blocked. Then,
+// allow JS and reload the page. In each case, only one of noscript or script
+// tags should be enabled, but never both.
+TEST_F(RenderFrameImplTest, ContentSettingsNoscriptTag) {
+  // Navigate to a URL with script disabled.
+  auto common_params = GetCommonParamsForContentSettingsTest();
+  common_params->navigation_type =
+      blink::mojom::NavigationType::DIFFERENT_DOCUMENT;
+  blink::mojom::CommitNavigationParamsPtr commit_params =
+      blink::CreateCommitNavigationParams();
+  commit_params->content_settings->allow_script = false;
+  content::TestRenderFrame* frame =
+      static_cast<TestRenderFrame*>(GetMainRenderFrame());
+
+  NavigateAndWait(frame, common_params->Clone(), commit_params->Clone(),
+                  web_view_);
+  EXPECT_TRUE(HasText(GetMainFrame(), "JS_DISABLED"));
+  EXPECT_FALSE(HasText(GetMainFrame(), "JS_ENABLED"));
+
+  // Reload the page but allow Javascript.
+  common_params->navigation_type = blink::mojom::NavigationType::RELOAD;
+  commit_params->content_settings->allow_script = true;
+  NavigateAndWait(frame, common_params->Clone(), commit_params->Clone(),
+                  web_view_);
+  EXPECT_FALSE(HasText(GetMainFrame(), "JS_DISABLED"));
+  EXPECT_TRUE(HasText(GetMainFrame(), "JS_ENABLED"));
+}
+
+// Checks that same document navigations don't update content settings for the
+// page.
+TEST_F(RenderFrameImplTest, ContentSettingsSameDocumentNavigation) {
+  // Load a page which contains a script.
+  auto common_params = GetCommonParamsForContentSettingsTest();
+  common_params->navigation_type =
+      blink::mojom::NavigationType::DIFFERENT_DOCUMENT;
+  blink::mojom::CommitNavigationParamsPtr commit_params =
+      blink::CreateCommitNavigationParams();
+  content::TestRenderFrame* frame =
+      static_cast<TestRenderFrame*>(GetMainRenderFrame());
+
+  NavigateAndWait(frame, common_params->Clone(), commit_params->Clone(),
+                  web_view_);
+
+  // Verify that the script was not blocked.
+  EXPECT_FALSE(HasText(GetMainFrame(), "JS_DISABLED"));
+  EXPECT_TRUE(HasText(GetMainFrame(), "JS_ENABLED"));
+
+  RenderFrameImpl* main_frame = GetMainRenderFrame();
+
+  main_frame->DidFinishSameDocumentNavigation(
+      blink::kWebStandardCommit,
+      /*is_synchronously_committed=*/true,
+      blink::mojom::SameDocumentNavigationType::kFragment,
+      /*is_client_redirect=*/false);
+
+  // Verify that the script was not blocked.
+  EXPECT_FALSE(HasText(GetMainFrame(), "JS_DISABLED"));
+  EXPECT_TRUE(HasText(GetMainFrame(), "JS_ENABLED"));
+}
+
 }  // namespace content
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index 4719563..4253408 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//build/config/ozone.gni")
diff --git a/content/shell/browser/shell_federated_permission_context.cc b/content/shell/browser/shell_federated_permission_context.cc
index 190e45d7..0fa41473 100644
--- a/content/shell/browser/shell_federated_permission_context.cc
+++ b/content/shell/browser/shell_federated_permission_context.cc
@@ -92,35 +92,6 @@
   idp_signin_status_observer_list_.RemoveObserver(observer);
 }
 
-// FederatedIdentityActiveSessionPermissionContextDelegate
-bool ShellFederatedPermissionContext::HasActiveSession(
-    const url::Origin& relying_party_requester,
-    const url::Origin& identity_provider,
-    const std::string& account_identifier) {
-  return base::Contains(
-      active_sessions_,
-      std::tuple(relying_party_requester.Serialize(),
-                 identity_provider.Serialize(), account_identifier));
-}
-
-void ShellFederatedPermissionContext::GrantActiveSession(
-    const url::Origin& relying_party_requester,
-    const url::Origin& identity_provider,
-    const std::string& account_identifier) {
-  active_sessions_.insert(std::tuple(relying_party_requester.Serialize(),
-                                     identity_provider.Serialize(),
-                                     account_identifier));
-}
-
-void ShellFederatedPermissionContext::RevokeActiveSession(
-    const url::Origin& relying_party_requester,
-    const url::Origin& identity_provider,
-    const std::string& account_identifier) {
-  active_sessions_.erase(std::tuple(relying_party_requester.Serialize(),
-                                    identity_provider.Serialize(),
-                                    account_identifier));
-}
-
 bool ShellFederatedPermissionContext::HasSharingPermission(
     const url::Origin& relying_party_requester,
     const url::Origin& relying_party_embedder,
diff --git a/content/shell/browser/shell_federated_permission_context.h b/content/shell/browser/shell_federated_permission_context.h
index 94ca1c8..bfb904f 100644
--- a/content/shell/browser/shell_federated_permission_context.h
+++ b/content/shell/browser/shell_federated_permission_context.h
@@ -59,15 +59,6 @@
   void AddIdpSigninStatusObserver(IdpSigninStatusObserver* observer) override;
   void RemoveIdpSigninStatusObserver(
       IdpSigninStatusObserver* observer) override;
-  bool HasActiveSession(const url::Origin& relying_party_requester,
-                        const url::Origin& identity_provider,
-                        const std::string& account_identifier) override;
-  void GrantActiveSession(const url::Origin& relying_party_requester,
-                          const url::Origin& identity_provider,
-                          const std::string& account_identifier) override;
-  void RevokeActiveSession(const url::Origin& relying_party_requester,
-                           const url::Origin& identity_provider,
-                           const std::string& account_identifier) override;
   bool HasSharingPermission(
       const url::Origin& relying_party_requester,
       const url::Origin& relying_party_embedder,
@@ -98,8 +89,6 @@
   // Tuples of <RP requester, RP embedder, IDP, Account>
   std::set<std::tuple<std::string, std::string, std::string, std::string>>
       sharing_permissions_;
-  // Tuples of <RP requester, IDP, Account>
-  std::set<std::tuple<std::string, std::string, std::string>> active_sessions_;
   // Map of <IDP, IDPSigninStatus>
   std::map<std::string, absl::optional<bool>> idp_signin_status_;
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 0967c510..6002770 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/compiler/compiler.gni")
 import("//build/config/features.gni")
@@ -2728,7 +2728,6 @@
     "../browser/web_package/signed_exchange_signature_header_field_unittest.cc",
     "../browser/web_package/signed_exchange_signature_verifier_unittest.cc",
     "../browser/web_package/signed_exchange_utils_unittest.cc",
-    "../browser/webid/federated_auth_request_impl_logout_unittest.cc",
     "../browser/webid/federated_auth_request_impl_multiple_frames_unittest.cc",
     "../browser/webid/federated_auth_request_impl_registry_unittest.cc",
     "../browser/webid/federated_auth_request_impl_unittest.cc",
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-assist-data.txt b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-assist-data.txt
index e4fbca82..01deae1 100644
--- a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-assist-data.txt
+++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-assist-data.txt
@@ -1,12 +1,13 @@
 WebView textSize:16.00 style:0 bundle:[display="", htmlTag="#document"]
-++EditText text:"Important stuff My name is Garaventa the weird. (QED) Where are my marbles?" textSize:13.33 style:0 bundle:[aria-describedby="descId", aria-label="Important stuff", display="inline-block", htmlTag="input", id="test", type="text"]
+++EditText text:"Important stuff My name is Eli the weird. (QED) Where are my marbles?" textSize:13.33 style:0 bundle:[aria-describedby="descId", aria-label="Important stuff", display="inline-block", htmlTag="input", id="test", type="text"]
 ++++View textSize:13.33 style:0 bundle:[display="flow-root", htmlTag="div"]
 ++View textSize:16.00 style:0 bundle:[display="block", htmlTag="div", id="descId"]
 ++++TextView text:"My" textSize:16.00 style:0 bundle:[display="", htmlTag=""]
 ++++TextView text:" name is" textSize:16.00 style:0 bundle:[display="", htmlTag=""]
 ++++View textSize:16.00 style:0 bundle:[display="block", htmlTag="div"]
-++++View text:"Garaventa" textSize:16.00 style:0 bundle:[aria-label="Garaventa", display="inline", htmlTag="span"]
-++++++TextView text:"Zambino" textSize:16.00 style:0 bundle:[display="", htmlTag=""]
+++++View text:"Eli" textSize:16.00 style:0 bundle:[aria-label="Eli", display="inline", htmlTag="span", role="presentation"]
+++++++View text:"Garaventa" textSize:16.00 style:0 bundle:[aria-label="Garaventa", display="inline", htmlTag="span"]
+++++++++TextView text:"Zambino" textSize:16.00 style:0 bundle:[display="", htmlTag=""]
 ++++TextView text:"the weird." textSize:16.00 style:0 bundle:[display="", htmlTag=""]
 ++++TextView text:" (QED)" textSize:16.00 style:0 bundle:[display="", htmlTag=""]
 ++++View textSize:16.00 style:0 bundle:[display="table", htmlTag="table"]
@@ -15,4 +16,4 @@
 ++++++++++TextView text:"Where" textSize:16.00 style:0 bundle:[display="", htmlTag=""]
 ++++++++View textSize:16.00 style:0 bundle:[display="table-cell", htmlTag="td"]
 ++++++++View textSize:16.00 style:0 bundle:[display="table-cell", htmlTag="td"]
-++++++++++TextView text:"are my marbles?" textSize:16.00 style:0 bundle:[display="", htmlTag=""]
\ No newline at end of file
+++++++++++TextView text:"are my marbles?" textSize:16.00 style:0 bundle:[display="", htmlTag=""]
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt
index 0dc7bb2d..e7696a3e 100644
--- a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt
+++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt
@@ -1,14 +1,15 @@
 WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"]
-++EditText hint:"Important stuff My name is Garaventa the weird. (QED) Where are my marbles?" viewIdResName:"test" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Important stuff My name is Garaventa the weird. (QED) Where are my marbles?"]
+++EditText hint:"Important stuff My name is Eli the weird. (QED) Where are my marbles?" viewIdResName:"test" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Important stuff My name is Eli the weird. (QED) Where are my marbles?"]
 ++View viewIdResName:"descId" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"]
 ++++TextView text:"My" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
 ++++TextView text:" name is" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
 ++++TextView actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"]
-++++TextView text:"Garaventa" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"]
+++++View text:"Eli" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"]
+++++++TextView text:"Garaventa" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"]
 ++++TextView text:"the weird." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
 ++++TextView text:" (QED)" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
 ++++View actions:[AX_FOCUS] bundle:[chromeRole="layoutTable"]
 ++++++View actions:[AX_FOCUS] bundle:[chromeRole="layoutTableRow"]
 ++++++++View text:"Where" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="layoutTableCell"]
 ++++++++View actions:[AX_FOCUS] bundle:[chromeRole="layoutTableCell"]
-++++++++View text:"are my marbles?" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="layoutTableCell"]
\ No newline at end of file
+++++++++View text:"are my marbles?" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="layoutTableCell"]
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android.txt b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android.txt
index 45164c2..5fc88c7 100644
--- a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android.txt
+++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android.txt
@@ -1 +1 @@
-android.widget.EditText hint='Important stuff My name is Garaventa the weird. (QED) Where are my marbles?' input_type=1
+android.widget.EditText hint='Important stuff My name is Eli the weird. (QED) Where are my marbles?' input_type=1
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-auralinux.txt b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-auralinux.txt
index 0a24be06..f9611c1 100644
--- a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-auralinux.txt
+++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-auralinux.txt
@@ -1 +1 @@
-[entry] description='My name is Garaventa the weird. (QED) Where are my marbles?' described-by=[section] description-from:aria-describedby
+[entry] description='My name is Eli the weird. (QED) Where are my marbles?' described-by=[section] description-from:aria-describedby
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-blink.txt b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-blink.txt
index de4fdc6cf..373c598 100644
--- a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-blink.txt
+++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-blink.txt
@@ -1,4 +1,4 @@
-# Original expectation was missing a space ("Garaventathe"), but the spec is not
+# Original expectation was missing a space ("Elithe"), but the spec is not
 # clear about this and it seems wrong, the result should match the rendered text
 # more closely. See: https://github.com/w3c/accname/issues/15
-textField description='My name is Garaventa the weird. (QED) Where are my marbles?' descriptionFrom=relatedElement
+textField description='My name is Eli the weird. (QED) Where are my marbles?' descriptionFrom=relatedElement
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-mac.txt b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-mac.txt
index 0a71ab99..361094b8 100644
--- a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-mac.txt
+++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-mac.txt
@@ -1 +1 @@
-AXTextField accessibilityCustomContent=[{label: 'description', value: 'My name is Garaventa the weird. (QED) Where are my marbles?'}]
+AXTextField accessibilityCustomContent=[{label: 'description', value: 'My name is Eli the weird. (QED) Where are my marbles?'}]
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-win.txt b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-win.txt
index 8f35977d..311e839 100644
--- a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-win.txt
+++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-win.txt
@@ -1 +1 @@
-ROLE_SYSTEM_TEXT FOCUSABLE description-from:aria-describedby description='My name is Garaventa the weird. (QED) Where are my marbles?'
+ROLE_SYSTEM_TEXT FOCUSABLE description-from:aria-describedby description='My name is Eli the weird. (QED) Where are my marbles?'
diff --git a/content/test/data/accessibility/accname/name-from-content-expected-blink.txt b/content/test/data/accessibility/accname/name-from-content-expected-blink.txt
index bbcfb2ed..1d5ba97 100644
--- a/content/test/data/accessibility/accname/name-from-content-expected-blink.txt
+++ b/content/test/data/accessibility/accname/name-from-content-expected-blink.txt
@@ -1,4 +1,4 @@
-# Original expectation was missing a space ("Garaventathe"), but the spec is not
+# Original expectation was missing a space ("Elithe"), but the spec is not
 # clear about this and it seems wrong, the result should match the rendered text
 # more closely. See: https://github.com/w3c/accname/issues/15
-link name='My name is Garaventa the weird. (QED) Where are my marbles?' nameFrom=contents
+link name='My name is Eli the weird. (QED) Where are my marbles?' nameFrom=contents
diff --git a/content/test/data/accessibility/accname/name-from-content-of-label-expected-blink.txt b/content/test/data/accessibility/accname/name-from-content-of-label-expected-blink.txt
index d4de3cf..b4bb6b5 100644
--- a/content/test/data/accessibility/accname/name-from-content-of-label-expected-blink.txt
+++ b/content/test/data/accessibility/accname/name-from-content-of-label-expected-blink.txt
@@ -1,4 +1,4 @@
-# Original expectation was missing a space ("Garaventathe"), but the spec is not
+# Original expectation was missing a space ("Elithe"), but the spec is not
 # clear about this and it seems wrong, the result should match the rendered text
 # more closely. See: https://github.com/w3c/accname/issues/15
-textField name='My name is Garaventa the weird. (QED) Where are my marbles?' nameFrom=relatedElement
+textField name='My name is Eli the weird. (QED) Where are my marbles?' nameFrom=relatedElement
diff --git a/content/test/data/accessibility/accname/name-from-content-of-labelledby-element-expected-blink.txt b/content/test/data/accessibility/accname/name-from-content-of-labelledby-element-expected-blink.txt
index d4de3cf..b4bb6b5 100644
--- a/content/test/data/accessibility/accname/name-from-content-of-labelledby-element-expected-blink.txt
+++ b/content/test/data/accessibility/accname/name-from-content-of-labelledby-element-expected-blink.txt
@@ -1,4 +1,4 @@
-# Original expectation was missing a space ("Garaventathe"), but the spec is not
+# Original expectation was missing a space ("Elithe"), but the spec is not
 # clear about this and it seems wrong, the result should match the rendered text
 # more closely. See: https://github.com/w3c/accname/issues/15
-textField name='My name is Garaventa the weird. (QED) Where are my marbles?' nameFrom=relatedElement
+textField name='My name is Eli the weird. (QED) Where are my marbles?' nameFrom=relatedElement
diff --git a/content/test/data/accessibility/accname/name-link-mixed-content-expected-blink.txt b/content/test/data/accessibility/accname/name-link-mixed-content-expected-blink.txt
index 80c1b5f..41cb85f 100644
--- a/content/test/data/accessibility/accname/name-link-mixed-content-expected-blink.txt
+++ b/content/test/data/accessibility/accname/name-link-mixed-content-expected-blink.txt
@@ -1,4 +1,4 @@
-# Original expectation was missing a space ("Garaventathe"), but the spec is not
+# Original expectation was missing a space ("Elithe"), but the spec is not
 # clear about this and it seems wrong, the result should match the rendered text
 # more closely. See: https://github.com/w3c/accname/issues/15
-link name='My name is Garaventa the weird. (QED)' nameFrom=contents
+link name='My name is Eli the weird. (QED)' nameFrom=contents
diff --git a/content/test/data/accessibility/aria/aria-expanded-roles-supported-expected-blink.txt b/content/test/data/accessibility/aria/aria-expanded-roles-supported-expected-blink.txt
index b4603e61..9efae97 100644
--- a/content/test/data/accessibility/aria/aria-expanded-roles-supported-expected-blink.txt
+++ b/content/test/data/accessibility/aria/aria-expanded-roles-supported-expected-blink.txt
@@ -37,7 +37,6 @@
 ++++++link expanded
 ++++++list
 ++++++listBox expanded
-++++++++listBoxOption
 ++++++listItem
 ++++++log
 ++++++main
@@ -51,6 +50,7 @@
 ++++++meter
 ++++++navigation
 ++++++note
+++++++listBoxOption
 ++++++paragraph
 ++++++progressIndicator
 ++++++radioButton
diff --git a/content/test/data/accessibility/aria/aria-expanded-roles-supported.html b/content/test/data/accessibility/aria/aria-expanded-roles-supported.html
index 719efa2..5dc1772 100644
--- a/content/test/data/accessibility/aria/aria-expanded-roles-supported.html
+++ b/content/test/data/accessibility/aria/aria-expanded-roles-supported.html
@@ -47,9 +47,7 @@
 <div role="legend" aria-expanded="true"></div>
 <div role="link" aria-expanded="true"></div>
 <div role="list" aria-expanded="true"></div>
-<div role="listbox" aria-expanded="true">
-  <div role="option" aria-expanded="true"></div>
-</div>
+<div role="listbox" aria-expanded="true"></div>
 <div role="listitem" aria-expanded="true"></div>
 <div role="log" aria-expanded="true"></div>
 <div role="main" aria-expanded="true"></div>
@@ -64,6 +62,7 @@
 <div role="navigation" aria-expanded="true"></div>
 <div role="none" aria-expanded="true"></div>
 <div role="note" aria-expanded="true"></div>
+<div role="option" aria-expanded="true"></div>
 <div role="paragraph" aria-expanded="true"></div>
 <div role="presentation" aria-expanded="true"></div>
 <div role="progressbar" aria-expanded="true"></div>
diff --git a/content/test/data/accessibility/aria/aria-leaf-in-editable-expected-blink.txt b/content/test/data/accessibility/aria/aria-leaf-in-editable-expected-blink.txt
index df6d1f5..a67b50d 100644
--- a/content/test/data/accessibility/aria/aria-leaf-in-editable-expected-blink.txt
+++ b/content/test/data/accessibility/aria/aria-leaf-in-editable-expected-blink.txt
@@ -17,10 +17,9 @@
 ++++++++menuItemCheckBox name='ARIA leaf content is not removed in editor' checkedState=false
 ++++++++++staticText name='ARIA leaf content is not removed in editor'
 ++++++++++++inlineTextBox name='ARIA leaf content is not removed in editor'
-++++++++listBox
-++++++++++listBoxOption name='ARIA leaf content is not removed in editor' selected=false
-++++++++++++staticText name='ARIA leaf content is not removed in editor'
-++++++++++++++inlineTextBox name='ARIA leaf content is not removed in editor'
+++++++++listBoxOption name='ARIA leaf content is not removed in editor' selected=false
+++++++++++staticText name='ARIA leaf content is not removed in editor'
+++++++++++++inlineTextBox name='ARIA leaf content is not removed in editor'
 ++++++++progressIndicator minValueForRange=0.00 maxValueForRange=100.00
 ++++++++++staticText name='ARIA leaf content is not removed in editor'
 ++++++++++++inlineTextBox name='ARIA leaf content is not removed in editor'
diff --git a/content/test/data/accessibility/aria/aria-leaf-in-editable.html b/content/test/data/accessibility/aria/aria-leaf-in-editable.html
index 8018ab8b..9ac0332 100644
--- a/content/test/data/accessibility/aria/aria-leaf-in-editable.html
+++ b/content/test/data/accessibility/aria/aria-leaf-in-editable.html
@@ -10,9 +10,7 @@
   <div role="menuitem">ARIA leaf content is not removed in editor</div>
   <div role="menuitemradio">ARIA leaf content is not removed in editor</div>
   <div role="menuitemcheckbox">ARIA leaf content is not removed in editor</div>
-  <div role="listbox">
-    <div role="option">ARIA leaf content is not removed in editor</div>
-  </div>
+  <div role="option">ARIA leaf content is not removed in editor</div>
   <div role="progressbar">ARIA leaf content is not removed in editor</div>
   <div role="radio">ARIA leaf content is not removed in editor</div>
   <div role="separator">ARIA leaf content is not removed in editor</div>
diff --git a/content/test/data/accessibility/html/dialog-expected-android-external.txt b/content/test/data/accessibility/html/dialog-expected-android-external.txt
index b18bca0..0faee2b 100644
--- a/content/test/data/accessibility/html/dialog-expected-android-external.txt
+++ b/content/test/data/accessibility/html/dialog-expected-android-external.txt
@@ -1,2 +1,2 @@
 WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"]
-++Dialog text:"Text in dialog" paneTitle:"dialog opened." focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"]
+++Dialog text:"Text in dialog" paneTitle:"dialog opened." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"]
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/dialog-expected-android.txt b/content/test/data/accessibility/html/dialog-expected-android.txt
index 91a5af1b..a00521f8 100644
--- a/content/test/data/accessibility/html/dialog-expected-android.txt
+++ b/content/test/data/accessibility/html/dialog-expected-android.txt
@@ -1,2 +1,2 @@
 android.webkit.WebView focusable focused scrollable
-++android.app.Dialog role_description='dialog' focusable name='Text in dialog'
+++android.app.Dialog role_description='dialog' name='Text in dialog'
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/dialog-expected-fuchsia.txt b/content/test/data/accessibility/html/dialog-expected-fuchsia.txt
index b37b420..0f7f56d 100644
--- a/content/test/data/accessibility/html/dialog-expected-fuchsia.txt
+++ b/content/test/data/accessibility/html/dialog-expected-fuchsia.txt
@@ -1,6 +1,6 @@
 UNKNOWN focusable has_input_focus
 ++UNKNOWN hidden
 ++++UNKNOWN hidden
-++++++UNKNOWN focusable
+++++++UNKNOWN
 ++++++++STATIC_TEXT label='Text in dialog'
-++++++++++UNKNOWN label='Text in dialog'
+++++++++++UNKNOWN label='Text in dialog'
\ No newline at end of file
diff --git a/content/test/data/accessibility/html/dialog-expected-uia-win.txt b/content/test/data/accessibility/html/dialog-expected-uia-win.txt
index 0bb79b0..002cbb2 100644
--- a/content/test/data/accessibility/html/dialog-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/dialog-expected-uia-win.txt
@@ -1,3 +1,3 @@
 Document
-++Window Window.IsModal=false
+++Window IsControlElement=false Window.IsModal=false
 ++++Text Name='Text in dialog'
diff --git a/content/test/data/accessibility/html/dialog-expected-win.txt b/content/test/data/accessibility/html/dialog-expected-win.txt
index 3c7f082..5cecfd7d 100644
--- a/content/test/data/accessibility/html/dialog-expected-win.txt
+++ b/content/test/data/accessibility/html/dialog-expected-win.txt
@@ -1,3 +1,3 @@
 ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
-++ROLE_SYSTEM_DIALOG FOCUSABLE
+++ROLE_SYSTEM_DIALOG
 ++++ROLE_SYSTEM_STATICTEXT name='Text in dialog'
diff --git a/content/test/data/accessibility/html/label-with-presentational-child-expected-blink.txt b/content/test/data/accessibility/html/label-with-presentational-child-expected-blink.txt
index 63b845b..61d46ea 100644
--- a/content/test/data/accessibility/html/label-with-presentational-child-expected-blink.txt
+++ b/content/test/data/accessibility/html/label-with-presentational-child-expected-blink.txt
@@ -1,12 +1,13 @@
 rootWebArea
 ++genericContainer ignored
 ++++genericContainer
-++++++textField name='bar'
+++++++textField name='foo'
 ++++++++genericContainer
 ++++++labelText
-++++++++genericContainer name='bar'
-++++++++++staticText name='baz'
-++++++++++++inlineTextBox name='baz'
+++++++++genericContainer name='foo'
+++++++++++genericContainer name='bar'
+++++++++++++staticText name='baz'
+++++++++++++++inlineTextBox name='baz'
 ++++++lineBreak name='<newline>'
 ++++++++inlineTextBox name='<newline>'
 ++++++textField name='bar'
diff --git a/content/test/data/accessibility/html/modal-dialog-opened-expected-android.txt b/content/test/data/accessibility/html/modal-dialog-opened-expected-android.txt
index 3821663..bd53d4cd 100644
--- a/content/test/data/accessibility/html/modal-dialog-opened-expected-android.txt
+++ b/content/test/data/accessibility/html/modal-dialog-opened-expected-android.txt
@@ -1,5 +1,5 @@
 android.webkit.WebView focusable scrollable
-++android.app.Dialog role_description='dialog' focusable
+++android.app.Dialog role_description='dialog'
 ++++android.widget.TextView name='The dialog subtree should be the only text content in the accessibility tree. '
 ++++android.view.View role_description='link' clickable focusable focused link name='Link inside the dialog.'
 ++++++android.widget.TextView name='Link inside the dialog.'
diff --git a/content/test/data/accessibility/html/modal-dialog-opened-expected-fuchsia.txt b/content/test/data/accessibility/html/modal-dialog-opened-expected-fuchsia.txt
index 40bbbb8..e181239 100644
--- a/content/test/data/accessibility/html/modal-dialog-opened-expected-fuchsia.txt
+++ b/content/test/data/accessibility/html/modal-dialog-opened-expected-fuchsia.txt
@@ -2,7 +2,7 @@
 ++UNKNOWN hidden
 ++++UNKNOWN hidden
 ++++++UNKNOWN hidden
-++++++++UNKNOWN focusable
+++++++++UNKNOWN
 ++++++++++STATIC_TEXT label='The dialog subtree should be the only text content in the accessibility tree. '
 ++++++++++++UNKNOWN label='The dialog subtree should be the only text content in the accessibility tree. '
 ++++++++++LINK focusable has_input_focus label='Link inside the dialog.' actions='{DEFAULT}'
diff --git a/content/test/data/accessibility/html/modal-dialog-opened-expected-uia-win.txt b/content/test/data/accessibility/html/modal-dialog-opened-expected-uia-win.txt
index bcd24fd..341f2a5 100644
--- a/content/test/data/accessibility/html/modal-dialog-opened-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/modal-dialog-opened-expected-uia-win.txt
@@ -1,5 +1,5 @@
 Document
-++Window Window.IsModal=true
+++Window IsControlElement=false Window.IsModal=true
 ++++Text Name='The dialog subtree should be the only text content in the accessibility tree. '
 ++++Hyperlink Name='Link inside the dialog.'
 ++++++Text Name='Link inside the dialog.' IsControlElement=false
diff --git a/content/test/data/accessibility/html/modal-dialog-opened-expected-win.txt b/content/test/data/accessibility/html/modal-dialog-opened-expected-win.txt
index f944e87..c134aa6 100644
--- a/content/test/data/accessibility/html/modal-dialog-opened-expected-win.txt
+++ b/content/test/data/accessibility/html/modal-dialog-opened-expected-win.txt
@@ -1,5 +1,5 @@
 ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
-++ROLE_SYSTEM_DIALOG FOCUSABLE IA2_STATE_MODAL
+++ROLE_SYSTEM_DIALOG IA2_STATE_MODAL
 ++++ROLE_SYSTEM_STATICTEXT name='The dialog subtree should be the only text content in the accessibility tree. '
 ++++ROLE_SYSTEM_LINK name='Link inside the dialog.' FOCUSABLE
 ++++++ROLE_SYSTEM_STATICTEXT name='Link inside the dialog.'
diff --git a/content/test/data/accessibility/html/modal-dialog-stack-expected-android.txt b/content/test/data/accessibility/html/modal-dialog-stack-expected-android.txt
index d3bed5e..8b85f273 100644
--- a/content/test/data/accessibility/html/modal-dialog-stack-expected-android.txt
+++ b/content/test/data/accessibility/html/modal-dialog-stack-expected-android.txt
@@ -1,4 +1,4 @@
 android.webkit.WebView focusable focused scrollable
-++android.app.Dialog role_description='dialog' focusable
+++android.app.Dialog role_description='dialog'
 ++++android.widget.TextView name='This is the now active dialog. Of course it should be in the tree. '
 ++++android.widget.Button role_description='button' clickable focusable name='This is in the active dialog and should be in the tree.'
diff --git a/content/test/data/accessibility/html/modal-dialog-stack-expected-fuchsia.txt b/content/test/data/accessibility/html/modal-dialog-stack-expected-fuchsia.txt
index 501fc15..d11f5ec 100644
--- a/content/test/data/accessibility/html/modal-dialog-stack-expected-fuchsia.txt
+++ b/content/test/data/accessibility/html/modal-dialog-stack-expected-fuchsia.txt
@@ -8,7 +8,7 @@
 ++++++++++UNKNOWN hidden
 ++++++UNKNOWN hidden
 ++++++++STATIC_TEXT hidden label='<newline>  This was the middle dialog and should be marked ignored in the tree.<newline>'
-++++++UNKNOWN focusable
+++++++UNKNOWN
 ++++++++STATIC_TEXT label='This is the now active dialog. Of course it should be in the tree. '
 ++++++++++UNKNOWN label='This is the now active dialog. Of course it should be in the tree. '
 ++++++++BUTTON focusable label='This is in the active dialog and should be in the tree.' actions='{DEFAULT}'
diff --git a/content/test/data/accessibility/html/modal-dialog-stack-expected-uia-win.txt b/content/test/data/accessibility/html/modal-dialog-stack-expected-uia-win.txt
index ae292bd1..b37f7026 100644
--- a/content/test/data/accessibility/html/modal-dialog-stack-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/modal-dialog-stack-expected-uia-win.txt
@@ -1,4 +1,4 @@
 Document
-++Window Window.IsModal=true
+++Window IsControlElement=false Window.IsModal=true
 ++++Text Name='This is the now active dialog. Of course it should be in the tree. '
 ++++Button Name='This is in the active dialog and should be in the tree.'
diff --git a/content/test/data/accessibility/html/modal-dialog-stack-expected-win.txt b/content/test/data/accessibility/html/modal-dialog-stack-expected-win.txt
index c2e96d3c..6371f34 100644
--- a/content/test/data/accessibility/html/modal-dialog-stack-expected-win.txt
+++ b/content/test/data/accessibility/html/modal-dialog-stack-expected-win.txt
@@ -1,4 +1,4 @@
 ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
-++ROLE_SYSTEM_DIALOG FOCUSABLE IA2_STATE_MODAL
+++ROLE_SYSTEM_DIALOG IA2_STATE_MODAL
 ++++ROLE_SYSTEM_STATICTEXT name='This is the now active dialog. Of course it should be in the tree. '
 ++++ROLE_SYSTEM_PUSHBUTTON name='This is in the active dialog and should be in the tree.' FOCUSABLE
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 b451cb6..edfafd92 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -416,6 +416,9 @@
 # Fails almost consistently, but likely to pass when run on its own in the retry.
 crbug.com/1484212 [ win debug nvidia ] Pixel_WebGL2_BlitFramebuffer_Result_Displayed [ RetryOnFailure ]
 
+# Fails with hung renderer
+crbug.com/1372149 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] Pixel_WebGLFloat [ Failure ]
+
 #######################################################################
 # Automated Entries After This Point - Do Not Manually Add Below Here #
 #######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index dff0a6f..b84b0f1 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -651,7 +651,25 @@
 crbug.com/1372155 [ android android-sm-a135m no-passthrough ] conformance/rendering/blending.html [ Failure ]
 crbug.com/1372155 [ android android-sm-a135m ] conformance/uniforms/uniform-samplers-test.html [ Failure ]
 crbug.com/1372149 [ android android-sm-a235m no-passthrough ] conformance/rendering/blending.html [ Failure ]
-
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/extensions/ext-color-buffer-half-float.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/extensions/oes-texture-float-with-video.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/extensions/oes-texture-float.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/extensions/oes-texture-half-float-with-video.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/image_bitmap_from_video/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/image_bitmap_from_video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_byte.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_byte.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/misc/video-rotation.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/video/tex-2d-rgb-rgb-unsigned_byte.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/video/tex-2d-rgba-rgba-unsigned_byte.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html [ Failure ]
+crbug.com/1499000 [ android android-sm-a235m no-passthrough renderer-skia-vulkan ] conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ Failure ]
 
 ############
 # ChromeOS #
diff --git a/content/web_test/BUILD.gn b/content/web_test/BUILD.gn
index e2a496c..e17c43b 100644
--- a/content/web_test/BUILD.gn
+++ b/content/web_test/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/ui.gni")  # For the toolkit_views variables.
 import("//mojo/public/tools/bindings/mojom.gni")
 import("//ppapi/buildflags/buildflags.gni")  # For the enable_plugins variable.
diff --git a/content/web_test/renderer/text_input_controller.cc b/content/web_test/renderer/text_input_controller.cc
index 14e4911..f6a32dd7 100644
--- a/content/web_test/renderer/text_input_controller.cc
+++ b/content/web_test/renderer/text_input_controller.cc
@@ -52,8 +52,8 @@
   void DoCommand(const std::string& text);
   void ExtendSelectionAndDelete(int before, int after);
   void DeleteSurroundingText(int before, int after);
-  void SetMarkedText(const std::string& text, int start, int length);
-  void SetMarkedTextFromExistingText(int start, int end);
+  void SetMarkedText(const std::string& text, uint32_t start, uint32_t length);
+  void SetMarkedTextFromExistingText(uint32_t start, uint32_t end);
   bool HasMarkedText();
   std::vector<int> MarkedRange();
   std::vector<int> SelectedRange();
@@ -161,14 +161,14 @@
 }
 
 void TextInputControllerBindings::SetMarkedText(const std::string& text,
-                                                int start,
-                                                int length) {
+                                                uint32_t start,
+                                                uint32_t length) {
   if (controller_)
     controller_->SetMarkedText(text, start, length);
 }
 
-void TextInputControllerBindings::SetMarkedTextFromExistingText(int start,
-                                                                int end) {
+void TextInputControllerBindings::SetMarkedTextFromExistingText(uint32_t start,
+                                                                uint32_t end) {
   if (controller_)
     controller_->SetMarkedTextFromExistingText(start, end);
 }
@@ -272,39 +272,43 @@
 }
 
 void TextInputController::SetMarkedText(const std::string& text,
-                                        int start,
-                                        int length) {
+                                        uint32_t start,
+                                        uint32_t length) {
   blink::WebString web_text(blink::WebString::FromUTF8(text));
 
   // Split underline into up to 3 elements (before, selection, and after).
   std::vector<ui::ImeTextSpan> ime_text_spans;
-  ui::ImeTextSpan ime_text_span;
-  if (!start) {
-    ime_text_span.end_offset = length;
+  ui::ImeTextSpan selection;
+  if (start) {
+    ui::ImeTextSpan before;
+    before.end_offset = start;
+    ime_text_spans.push_back(before);
+
+    selection.start_offset = start;
+    selection.end_offset = base::ClampedNumeric(start) + length;
   } else {
-    ime_text_span.end_offset = start;
-    ime_text_spans.push_back(ime_text_span);
-    ime_text_span.start_offset = start;
-    ime_text_span.end_offset = start + length;
+    selection.end_offset = length;
   }
-  ime_text_span.thickness = ui::ImeTextSpan::Thickness::kThick;
-  ime_text_span.underline_style = ui::ImeTextSpan::UnderlineStyle::kSolid;
-  ime_text_spans.push_back(ime_text_span);
-  if (start + length < static_cast<int>(web_text.length())) {
-    ime_text_span.start_offset = ime_text_span.end_offset;
-    ime_text_span.end_offset = web_text.length();
-    ime_text_span.thickness = ui::ImeTextSpan::Thickness::kThin;
-    ime_text_span.underline_style = ui::ImeTextSpan::UnderlineStyle::kSolid;
-    ime_text_spans.push_back(ime_text_span);
+  if (selection.end_offset != selection.start_offset) {
+    selection.thickness = ui::ImeTextSpan::Thickness::kThick;
+    selection.underline_style = ui::ImeTextSpan::UnderlineStyle::kSolid;
+    ime_text_spans.push_back(selection);
+  }
+  if (selection.end_offset < web_text.length()) {
+    ui::ImeTextSpan after;
+    after.start_offset = selection.end_offset;
+    after.end_offset = web_text.length();
+    ime_text_spans.push_back(after);
   }
 
   if (auto* controller = GetInputMethodController()) {
     controller->SetComposition(web_text, ime_text_spans, blink::WebRange(),
-                               start, start + length);
+                               selection.start_offset, selection.end_offset);
   }
 }
 
-void TextInputController::SetMarkedTextFromExistingText(int start, int end) {
+void TextInputController::SetMarkedTextFromExistingText(uint32_t start,
+                                                        uint32_t end) {
   if (!view()->MainFrame())
     return;
 
diff --git a/content/web_test/renderer/text_input_controller.h b/content/web_test/renderer/text_input_controller.h
index e3f59b9..a988b20 100644
--- a/content/web_test/renderer/text_input_controller.h
+++ b/content/web_test/renderer/text_input_controller.h
@@ -44,8 +44,8 @@
   void DoCommand(const std::string& text);
   void ExtendSelectionAndDelete(int before, int after);
   void DeleteSurroundingText(int before, int after);
-  void SetMarkedText(const std::string& text, int start, int length);
-  void SetMarkedTextFromExistingText(int start, int end);
+  void SetMarkedText(const std::string& text, uint32_t start, uint32_t length);
+  void SetMarkedTextFromExistingText(uint32_t start, uint32_t end);
   bool HasMarkedText();
   std::vector<int> MarkedRange();
   std::vector<int> SelectedRange();
diff --git a/device/vr/buildflags/buildflags.gni b/device/vr/buildflags/buildflags.gni
index 6f69f9e..8b73378 100644
--- a/device/vr/buildflags/buildflags.gni
+++ b/device/vr/buildflags/buildflags.gni
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/gclient_args.gni")
 
@@ -13,7 +13,7 @@
 # like to support on Android by default. Embedders can still override any of
 # the particular runtimes if they do not wish to enable them.
 _is_xr_supported_android = is_android && !is_cast_android &&
-                          (current_cpu == "arm" || current_cpu == "arm64")
+                           (current_cpu == "arm" || current_cpu == "arm64")
 
 declare_args() {
   enable_gvr_services = _is_xr_supported_android
diff --git a/docs/testing_webui.md b/docs/testing_webui.md
index f385cafc..2feeebd8 100644
--- a/docs/testing_webui.md
+++ b/docs/testing_webui.md
@@ -72,6 +72,12 @@
 
 ```
 
+Note: If testing a `chrome-untrusted://` UI, also call:
+```
+set_test_loader_scheme(content::kChromeUIUntrustedScheme);
+```
+in the constructor.
+
 After defining the class, create one or more `IN_PROC_BROWSER_TEST_F`
 functions. Each should run one or more Mocha tests.
 
@@ -224,6 +230,10 @@
 }
 ```
 
+Note: If testing a `chrome-untrusted://` UI, also set the
+`is_chrome_untrusted` parameter for `build_webui_tests()` to `true`, to allow
+importing shared test files from `chrome-untrusted://webui-test/` paths.
+
 You then need to hook up the targets generated by this file, and list your
 browsertest.cc source file, in `chrome/test/data/webui/BUILD.gn`:
 
diff --git a/docs/webui_build_configuration.md b/docs/webui_build_configuration.md
index 7cc2996..f783a966 100644
--- a/docs/webui_build_configuration.md
+++ b/docs/webui_build_configuration.md
@@ -650,6 +650,10 @@
 
 #### **Arguments**
 ```
+is_chrome_untrusted: Set to true if testing a chrome-untrusted:// UI. Optional
+                     parameter. Allows importing shared test files from
+                     chrome-untrusted://webui-test/ instead of
+                     chrome://webui-test.
 
 List of files params:
 files: Required parameter. List of all test related files.
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn
index 202801d..eacccd0 100644
--- a/extensions/BUILD.gn
+++ b/extensions/BUILD.gn
@@ -1,7 +1,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//extensions/buildflags/buildflags.gni")
 import("//testing/test.gni")
diff --git a/extensions/browser/api/messaging/extension_message_port.cc b/extensions/browser/api/messaging/extension_message_port.cc
index 4630ca2..331a3edb 100644
--- a/extensions/browser/api/messaging/extension_message_port.cc
+++ b/extensions/browser/api/messaging/extension_message_port.cc
@@ -445,8 +445,8 @@
 
     ExtensionWebContentsObserver::GetForWebContents(
         content::WebContents::FromRenderFrameHost(frame))
-        ->GetLocalFrame(frame)
-        ->DispatchOnConnect(
+        ->GetLocalFrameChecked(frame)
+        .DispatchOnConnect(
             port_id_, channel_type, channel_name, source.Clone(), info.Clone(),
             std::move(message_port), std::move(message_port_host),
             base::BindOnce(&ExtensionMessagePort::OnConnectResponse,
diff --git a/extensions/browser/app_window/app_window_contents.cc b/extensions/browser/app_window/app_window_contents.cc
index 0e588f7..fa644741 100644
--- a/extensions/browser/app_window/app_window_contents.cc
+++ b/extensions/browser/app_window/app_window_contents.cc
@@ -74,9 +74,9 @@
     return;
   }
   ExtensionWebContentsObserver::GetForWebContents(web_contents())
-      ->GetLocalFrame(render_frame_host)
-      ->MessageInvoke(host_->extension_id(), "app.window",
-                      "updateAppWindowProperties", std::move(args));
+      ->GetLocalFrameChecked(render_frame_host)
+      .MessageInvoke(host_->extension_id(), "app.window",
+                     "updateAppWindowProperties", std::move(args));
 }
 
 void AppWindowContentsImpl::NativeWindowClosed(bool send_onclosed) {
@@ -84,8 +84,8 @@
   if (!web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive())
     return;
   ExtensionWebContentsObserver::GetForWebContents(web_contents())
-      ->GetLocalFrame(web_contents_->GetPrimaryMainFrame())
-      ->AppWindowClosed(send_onclosed);
+      ->GetLocalFrameChecked(web_contents_->GetPrimaryMainFrame())
+      .AppWindowClosed(send_onclosed);
 }
 
 content::WebContents* AppWindowContentsImpl::GetWebContents() const {
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index a3a6212..24c80686 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1899,6 +1899,7 @@
   OS_DIAGNOSTICS_ISVOLUMEBUTTONROUTINEARGUMENTSUPPORTED = 1837,
   USERSCRIPTS_CONFIGUREWORLD = 1838,
   ENTERPRISE_KIOSKINPUT_SETCURRENTINPUTMETHOD = 1839,
+  AUTOFILLPRIVATE_BULKDELETEALLCVCS = 1840,
   // Last entry: Add new entries above, then run:
   // tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/extensions/browser/extension_web_contents_observer.cc b/extensions/browser/extension_web_contents_observer.cc
index ea7cd3b3..d86fbd5 100644
--- a/extensions/browser/extension_web_contents_observer.cc
+++ b/extensions/browser/extension_web_contents_observer.cc
@@ -85,6 +85,12 @@
 
   web_contents()->ForEachRenderFrameHost(
       [this](content::RenderFrameHost* render_frame_host) {
+        // ForEachRenderFrameHost descends into inner WebContents, so make sure
+        // the RenderFrameHost is actually one bound to this object.
+        if (content::WebContents::FromRenderFrameHost(render_frame_host) !=
+            web_contents()) {
+          return;
+        }
         // We only initialize the frame if the renderer counterpart is live;
         // otherwise we wait for the RenderFrameCreated notification.
         if (render_frame_host->IsRenderFrameLive())
@@ -135,8 +141,8 @@
   security_policy->GrantRequestOrigin(process_id, frame_extension->origin());
 
   // Notify the render frame of the view type.
-  GetLocalFrame(render_frame_host)
-      ->NotifyRenderViewType(GetViewType(web_contents()));
+  GetLocalFrameChecked(render_frame_host)
+      .NotifyRenderViewType(GetViewType(web_contents()));
 
   ProcessManager::Get(browser_context_)
       ->RegisterRenderFrameHost(web_contents(), render_frame_host,
@@ -357,6 +363,14 @@
   if (!render_frame_host->IsRenderFrameLive())
     return nullptr;
 
+  // Do not return a LocalFrame object for frames that do not immediately belong
+  // to this WebContents. For example frames belonging to inner WebContents will
+  // have their own ExtensionWebContentsObserver.
+  if (content::WebContents::FromRenderFrameHost(render_frame_host) !=
+      web_contents()) {
+    return nullptr;
+  }
+
   mojo::AssociatedRemote<mojom::LocalFrame>& remote =
       local_frame_map_[render_frame_host];
   if (!remote.is_bound()) {
@@ -366,6 +380,13 @@
   return remote.get();
 }
 
+mojom::LocalFrame& ExtensionWebContentsObserver::GetLocalFrameChecked(
+    content::RenderFrameHost* render_frame_host) {
+  auto* local_frame = GetLocalFrame(render_frame_host);
+  CHECK(local_frame);
+  return *local_frame;
+}
+
 void ExtensionWebContentsObserver::OnWindowIdChanged(SessionID id) {
   web_contents()->ForEachRenderFrameHost(
       [&id, this](content::RenderFrameHost* render_frame_host) {
diff --git a/extensions/browser/extension_web_contents_observer.h b/extensions/browser/extension_web_contents_observer.h
index a3a8cc53..5382c55 100644
--- a/extensions/browser/extension_web_contents_observer.h
+++ b/extensions/browser/extension_web_contents_observer.h
@@ -88,12 +88,17 @@
       content::RenderFrameHost* render_frame_host,
       bool verify_url) const;
 
-  // Returns mojom::LocalFrame* corresponding |render_frame_host|. It emplaces
+  // Returns mojom::LocalFrame* corresponding `render_frame_host`. It emplaces
   // AssociatedRemote<mojom::LocalFrame> to |local_frame_map_| if the map
-  // doesn't have it. Note that it could return nullptr if |render_frame_host|
-  // is not live.
+  // doesn't have it. Note that it could return nullptr if `render_frame_host`
+  // is not live or `render_frame_host` does not immediately belong to the
+  // associated `WebContents`.
   mojom::LocalFrame* GetLocalFrame(content::RenderFrameHost* render_frame_host);
 
+  // Similar to `GetLocalFrame` but will not return nullptr, will crash.
+  mojom::LocalFrame& GetLocalFrameChecked(
+      content::RenderFrameHost* render_frame_host);
+
   // Tells the receiver to start listening to window ID changes from the
   // supplied SessionTabHelper. This method is public to allow the code that
   // installs new SessionTabHelpers to call it; that in turn is required because
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index d9710ca0..3f50bba8 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -1011,8 +1011,8 @@
 
   if (!render_frame_host->GetParentOrOuterDocument()) {
     ExtensionWebContentsObserver::GetForWebContents(web_contents())
-        ->GetLocalFrame(render_frame_host)
-        ->SetFrameName(name_);
+        ->GetLocalFrameChecked(render_frame_host)
+        .SetFrameName(name_);
     SetTransparency(render_frame_host);
   }
 }
@@ -1313,8 +1313,8 @@
     return;
   }
   ExtensionWebContentsObserver::GetForWebContents(web_contents())
-      ->GetLocalFrame(GetGuestMainFrame())
-      ->SetFrameName(name_);
+      ->GetLocalFrameChecked(GetGuestMainFrame())
+      .SetFrameName(name_);
 }
 
 void WebViewGuest::SetSpatialNavigationEnabled(bool enabled) {
@@ -1322,8 +1322,8 @@
     return;
   is_spatial_navigation_enabled_ = enabled;
   ExtensionWebContentsObserver::GetForWebContents(web_contents())
-      ->GetLocalFrame(web_contents()->GetPrimaryMainFrame())
-      ->SetSpatialNavigationEnabled(enabled);
+      ->GetLocalFrameChecked(web_contents()->GetPrimaryMainFrame())
+      .SetSpatialNavigationEnabled(enabled);
 }
 
 bool WebViewGuest::IsSpatialNavigationEnabled() const {
diff --git a/extensions/browser/script_executor.cc b/extensions/browser/script_executor.cc
index 66c68f7..2be17175 100644
--- a/extensions/browser/script_executor.cc
+++ b/extensions/browser/script_executor.cc
@@ -249,12 +249,12 @@
                                               host_id_);
     }
     ExtensionWebContentsObserver::GetForWebContents(web_contents())
-        ->GetLocalFrame(frame)
-        ->ExecuteCode(std::move(params),
-                      base::BindOnce(&Handler::OnExecuteCodeFinished,
-                                     weak_ptr_factory_.GetWeakPtr(),
-                                     frame->GetProcess()->GetID(),
-                                     frame->GetRoutingID()));
+        ->GetLocalFrameChecked(frame)
+        .ExecuteCode(std::move(params),
+                     base::BindOnce(&Handler::OnExecuteCodeFinished,
+                                    weak_ptr_factory_.GetWeakPtr(),
+                                    frame->GetProcess()->GetID(),
+                                    frame->GetRoutingID()));
   }
 
   // Handles the ExecuteCodeFinished message.
diff --git a/extensions/browser/service_worker/service_worker_host.cc b/extensions/browser/service_worker/service_worker_host.cc
index 60ccfc9..d8dc56a 100644
--- a/extensions/browser/service_worker/service_worker_host.cc
+++ b/extensions/browser/service_worker/service_worker_host.cc
@@ -271,9 +271,13 @@
   if (extension.id() != worker_id_.extension_id) {
     return;
   }
+  content::BrowserContext* browser_context = GetBrowserContext();
+  if (!browser_context) {
+    return;
+  }
   content::ServiceWorkerContext* context =
       util::GetServiceWorkerContextForExtensionId(worker_id_.extension_id,
-                                                  GetBrowserContext());
+                                                  browser_context);
   CHECK(context);
   if (!context->IsLiveRunningServiceWorker(worker_id_.version_id)) {
     return;
@@ -300,9 +304,14 @@
   bad_message::ReceivedBadMessage(render_process_host_,
                                   bad_message::LEGACY_IPC_MISMATCH);
 #else
+  content::BrowserContext* browser_context = GetBrowserContext();
+  if (!browser_context) {
+    return;
+  }
+
   MessageServiceApi::GetMessageService()->OpenChannelToExtension(
-      GetBrowserContext(), worker_id_, port_id, *info, channel_type,
-      channel_name, std::move(port), std::move(port_host));
+      browser_context, worker_id_, port_id, *info, channel_type, channel_name,
+      std::move(port), std::move(port_host));
 #endif
 }
 
@@ -318,9 +327,14 @@
   bad_message::ReceivedBadMessage(render_process_host_,
                                   bad_message::LEGACY_IPC_MISMATCH);
 #else
+  content::BrowserContext* browser_context = GetBrowserContext();
+  if (!browser_context) {
+    return;
+  }
+
   MessageServiceApi::GetMessageService()->OpenChannelToNativeApp(
-      GetBrowserContext(), worker_id_, port_id, native_app_name,
-      std::move(port), std::move(port_host));
+      browser_context, worker_id_, port_id, native_app_name, std::move(port),
+      std::move(port_host));
 #endif
 }
 
@@ -340,8 +354,13 @@
   bad_message::ReceivedBadMessage(render_process_host_,
                                   bad_message::LEGACY_IPC_MISMATCH);
 #else
+  content::BrowserContext* browser_context = GetBrowserContext();
+  if (!browser_context) {
+    return;
+  }
+
   MessageServiceApi::GetMessageService()->OpenChannelToTab(
-      GetBrowserContext(), worker_id_, port_id, tab_id, frame_id,
+      browser_context, worker_id_, port_id, tab_id, frame_id,
       document_id ? *document_id : std::string(), channel_type, channel_name,
       std::move(port), std::move(port_host));
 #endif
diff --git a/extensions/buildflags/buildflags.gni b/extensions/buildflags/buildflags.gni
index 14f3b0ba..2391406 100644
--- a/extensions/buildflags/buildflags.gni
+++ b/extensions/buildflags/buildflags.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 
 declare_args() {
   enable_extensions = !is_android && !is_ios && !is_castos
diff --git a/fuchsia_web/webengine/BUILD.gn b/fuchsia_web/webengine/BUILD.gn
index 6c43f35..a5761b70 100644
--- a/fuchsia_web/webengine/BUILD.gn
+++ b/fuchsia_web/webengine/BUILD.gn
@@ -4,7 +4,7 @@
 
 assert(is_fuchsia)
 
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/fuchsia/generate_runner_scripts.gni")
 import("//build/config/fuchsia/packaged_content_embedder_excluded_dirs.gni")
 import("//build/config/locales.gni")
diff --git a/gpu/command_buffer/client/shared_image_interface.h b/gpu/command_buffer/client/shared_image_interface.h
index e262f9e..70675910 100644
--- a/gpu/command_buffer/client/shared_image_interface.h
+++ b/gpu/command_buffer/client/shared_image_interface.h
@@ -213,7 +213,7 @@
   // The |SharedImageInterface| keeps ownership of the image until
   // |DestroySharedImage| is called or the interface itself is destroyed (e.g.
   // the GPU channel is lost).
-  virtual Mailbox CreateSharedImage(
+  virtual scoped_refptr<ClientSharedImage> CreateSharedImage(
       gfx::GpuMemoryBuffer* gpu_memory_buffer,
       GpuMemoryBufferManager* gpu_memory_buffer_manager,
       gfx::BufferPlane plane,
diff --git a/gpu/command_buffer/service/scheduler.cc b/gpu/command_buffer/service/scheduler.cc
index a0995d0..4767e5a 100644
--- a/gpu/command_buffer/service/scheduler.cc
+++ b/gpu/command_buffer/service/scheduler.cc
@@ -403,12 +403,7 @@
 
 Scheduler::Scheduler(SyncPointManager* sync_point_manager,
                      const GpuPreferences& gpu_preferences)
-    : sync_point_manager_(sync_point_manager),
-      blocked_time_collection_enabled_(
-          gpu_preferences.enable_gpu_blocked_time_metric) {
-  if (blocked_time_collection_enabled_ && !base::ThreadTicks::IsSupported())
-    DLOG(ERROR) << "GPU Blocked time collection is enabled but not supported.";
-
+    : sync_point_manager_(sync_point_manager) {
   if (base::FeatureList::IsEnabled(features::kUseGpuSchedulerDfs)) {
     scheduler_dfs_ =
         std::make_unique<SchedulerDfs>(sync_point_manager, gpu_preferences);
@@ -767,34 +762,16 @@
   thread_state = nullptr;
   sequence = nullptr;
 
-  base::TimeDelta blocked_time;
   {
     base::AutoUnlock auto_unlock(lock_);
     order_data->BeginProcessingOrderNumber(order_num);
 
-    if (blocked_time_collection_enabled_ && base::ThreadTicks::IsSupported()) {
-      // We can't call base::ThreadTicks::Now() if it's not supported
-      base::ThreadTicks thread_time_start = base::ThreadTicks::Now();
-      base::TimeTicks wall_time_start = base::TimeTicks::Now();
-
-      std::move(closure).Run();
-
-      base::TimeDelta thread_time_elapsed =
-          base::ThreadTicks::Now() - thread_time_start;
-      base::TimeDelta wall_time_elapsed =
-          base::TimeTicks::Now() - wall_time_start;
-
-      blocked_time += (wall_time_elapsed - thread_time_elapsed);
-    } else {
-      std::move(closure).Run();
-    }
+    std::move(closure).Run();
 
     if (order_data->IsProcessingOrderNumber())
       order_data->FinishProcessingOrderNumber(order_num);
   }
 
-  total_blocked_time_ += blocked_time;
-
   // Reset pointers after reaquiring the lock.
   thread_state = &per_thread_state_map_[task_runner];
   sequence = GetSequence(state.sequence_id);
@@ -826,18 +803,6 @@
                                                   base::Unretained(this)));
 }
 
-base::TimeDelta Scheduler::TakeTotalBlockingTime() {
-  if (scheduler_dfs_)
-    return scheduler_dfs_->TakeTotalBlockingTime();
-
-  if (!blocked_time_collection_enabled_ || !base::ThreadTicks::IsSupported())
-    return base::TimeDelta::Min();
-  base::AutoLock auto_lock(lock_);
-  base::TimeDelta result;
-  std::swap(result, total_blocked_time_);
-  return result;
-}
-
 base::SingleThreadTaskRunner* Scheduler::GetTaskRunnerForTesting(
     SequenceId sequence_id) {
   if (scheduler_dfs_) {
diff --git a/gpu/command_buffer/service/scheduler.h b/gpu/command_buffer/service/scheduler.h
index f1bdcefc..5231090 100644
--- a/gpu/command_buffer/service/scheduler.h
+++ b/gpu/command_buffer/service/scheduler.h
@@ -124,11 +124,6 @@
   // If the sequence should yield so that a higher priority sequence may run.
   bool ShouldYield(SequenceId sequence_id);
 
-  // Takes and resets current accumulated blocking time. Not available on all
-  // platforms. Must be enabled with --enable-gpu-blocked-time.
-  // Returns TimeDelta::Min() when not available.
-  base::TimeDelta TakeTotalBlockingTime();
-
   base::SingleThreadTaskRunner* GetTaskRunnerForTesting(SequenceId sequence_id);
 
   // Returns pointer to a SchedulerDfs instance if the feature flag
@@ -422,10 +417,6 @@
   base::flat_map<base::SingleThreadTaskRunner*, PerThreadState>
       per_thread_state_map_ GUARDED_BY(lock_);
 
-  // Accumulated time the thread was blocked during running task
-  base::TimeDelta total_blocked_time_ GUARDED_BY(lock_);
-  const bool blocked_time_collection_enabled_;
-
   // A pointer to a SchedulerDfs instance. If set, all public SchedulerDfs
   // methods are forwarded to this SchedulerDfs instance. |scheduler_dfs_| is
   // set depending on a Finch experimental feature.
diff --git a/gpu/command_buffer/service/scheduler_dfs.cc b/gpu/command_buffer/service/scheduler_dfs.cc
index 5a25c4cd..d540d58 100644
--- a/gpu/command_buffer/service/scheduler_dfs.cc
+++ b/gpu/command_buffer/service/scheduler_dfs.cc
@@ -279,12 +279,7 @@
 
 SchedulerDfs::SchedulerDfs(SyncPointManager* sync_point_manager,
                            const GpuPreferences& gpu_preferences)
-    : sync_point_manager_(sync_point_manager),
-      blocked_time_collection_enabled_(
-          gpu_preferences.enable_gpu_blocked_time_metric) {
-  if (blocked_time_collection_enabled_ && !base::ThreadTicks::IsSupported())
-    DLOG(ERROR) << "GPU Blocked time collection is enabled but not supported.";
-}
+    : sync_point_manager_(sync_point_manager) {}
 
 SchedulerDfs::~SchedulerDfs() {
   base::AutoLock auto_lock(lock_);
@@ -437,15 +432,6 @@
   return running_sequence->ShouldYieldTo(next_sequence);
 }
 
-base::TimeDelta SchedulerDfs::TakeTotalBlockingTime() {
-  if (!blocked_time_collection_enabled_ || !base::ThreadTicks::IsSupported())
-    return base::TimeDelta::Min();
-  base::AutoLock auto_lock(lock_);
-  base::TimeDelta result;
-  std::swap(result, total_blocked_time_);
-  return result;
-}
-
 base::SingleThreadTaskRunner* SchedulerDfs::GetTaskRunnerForTesting(
     SequenceId sequence_id) {
   base::AutoLock auto_lock(lock_);
@@ -751,22 +737,7 @@
     base::AutoUnlock auto_unlock(lock_);
     order_data->BeginProcessingOrderNumber(order_num);
 
-    if (blocked_time_collection_enabled_ && base::ThreadTicks::IsSupported()) {
-      // We can't call base::ThreadTicks::Now() if it's not supported
-      base::ThreadTicks thread_time_start = base::ThreadTicks::Now();
-      base::TimeTicks wall_time_start = base::TimeTicks::Now();
-
-      std::move(closure).Run();
-
-      base::TimeDelta thread_time_elapsed =
-          base::ThreadTicks::Now() - thread_time_start;
-      base::TimeDelta wall_time_elapsed =
-          base::TimeTicks::Now() - wall_time_start;
-
-      blocked_time += (wall_time_elapsed - thread_time_elapsed);
-    } else {
-      std::move(closure).Run();
-    }
+    std::move(closure).Run();
 
     if (order_data->IsProcessingOrderNumber())
       order_data->FinishProcessingOrderNumber(order_num);
diff --git a/gpu/command_buffer/service/scheduler_dfs.h b/gpu/command_buffer/service/scheduler_dfs.h
index d11d93a..871e9e87 100644
--- a/gpu/command_buffer/service/scheduler_dfs.h
+++ b/gpu/command_buffer/service/scheduler_dfs.h
@@ -89,11 +89,6 @@
   // If the sequence should yield so that a higher priority sequence may run.
   bool ShouldYield(SequenceId sequence_id);
 
-  // Takes and resets current accumulated blocking time. Not available on all
-  // platforms. Must be enabled with --enable-gpu-blocked-time.
-  // Returns TimeDelta::Min() when not available.
-  base::TimeDelta TakeTotalBlockingTime();
-
   base::SingleThreadTaskRunner* GetTaskRunnerForTesting(SequenceId sequence_id);
 
  private:
@@ -369,7 +364,6 @@
 
   // Accumulated time the thread was blocked during running task
   base::TimeDelta total_blocked_time_ GUARDED_BY(lock_);
-  const bool blocked_time_collection_enabled_;
 
  private:
   FRIEND_TEST_ALL_PREFIXES(SchedulerDfsTest, StreamPriorities);
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
index 1d0fa77b8..5bfa9cb 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
@@ -1064,7 +1064,7 @@
   return SkiaGraphiteDawnImageRepresentation::Create(
       std::move(dawn_representation), context_state,
       context_state->gpu_main_graphite_recorder(), manager, this, tracker,
-      plane_index_, is_yuv_plane);
+      is_yuv_plane);
 #else
   NOTREACHED_NORETURN();
 #endif
diff --git a/gpu/command_buffer/service/shared_image/dcomp_surface_image_backing.cc b/gpu/command_buffer/service/shared_image/dcomp_surface_image_backing.cc
index c84380e..78d7a982 100644
--- a/gpu/command_buffer/service/shared_image/dcomp_surface_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/dcomp_surface_image_backing.cc
@@ -290,7 +290,7 @@
   return SkiaGraphiteDawnImageRepresentation::Create(
       std::move(dawn_representation), context_state,
       context_state->gpu_main_graphite_recorder(), manager, this, tracker,
-      /*plane_index=*/0, /*is_yuv_plane=*/false);
+      /*is_yuv_plane=*/false);
 }
 
 Microsoft::WRL::ComPtr<ID3D11Texture2D> DCompSurfaceImageBacking::BeginDraw(
diff --git a/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.cc b/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.cc
index 5ddefed..b25c575 100644
--- a/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/dxgi_swap_chain_image_backing.cc
@@ -383,7 +383,7 @@
   return SkiaGraphiteDawnImageRepresentation::Create(
       std::move(dawn_representation), context_state,
       context_state->gpu_main_graphite_recorder(), manager, this, tracker,
-      /*plane_index=*/0, /*is_yuv_plane=*/false);
+      /*is_yuv_plane=*/false);
 }
 
 wgpu::Texture DXGISwapChainImageBacking::BeginAccessDawn(
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.cc
index d6022989..9fb8547 100644
--- a/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/external_vk_image_backing_factory.cc
@@ -66,9 +66,10 @@
     if (!HasVkFormat(format)) {
       return;
     }
-    VkFormat vk_format = format.PrefersExternalSampler()
-                             ? ToVkFormatExternalSampler(format)
-                             : ToVkFormatSinglePlanar(format);
+    // External sampler should only be used when creating shared image out of
+    // GpuMemoryBuffer.
+    CHECK(!format.PrefersExternalSampler());
+    VkFormat vk_format = ToVkFormatSinglePlanar(format);
     DCHECK_NE(vk_format, VK_FORMAT_UNDEFINED);
     VkFormatProperties format_props = {};
     vkGetPhysicalDeviceFormatProperties(vk_physical_device, vk_format,
@@ -85,15 +86,50 @@
     add_to_cache_if_supported(format);
   }
 
-#if BUILDFLAG(IS_OZONE)
-  // Support multiplanar formats with external sampling.
-  for (auto format : viz::MultiPlaneFormat::kAll) {
-    format.SetPrefersExternalSampler();
-    add_to_cache_if_supported(format);
+  return image_usage_cache;
+}
+
+bool IsFormatSupported(viz::SharedImageFormat format,
+                       gfx::GpuMemoryBufferType gmb_type) {
+#if BUILDFLAG(IS_LINUX)
+  if (format.IsLegacyMultiplanar() || format.PrefersExternalSampler()) {
+    // ExternalVkImageBacking doesn't work properly with external sampler
+    // multi-planar formats on Linux, see https://crbug.com/1394888.
+    return false;
   }
 #endif
 
-  return image_usage_cache;
+  if (format.is_multi_plane()) {
+    if (gmb_type != gfx::GpuMemoryBufferType::EMPTY_BUFFER) {
+      // Must prefer external sampler for GpuMemoryBuffers.
+      if (!format.PrefersExternalSampler()) {
+        return false;
+      }
+      if (ToVkFormatExternalSampler(format) == VK_FORMAT_UNDEFINED) {
+        return false;
+      }
+    } else {
+      // Cannot prefer external sampler for non-GMB cases.
+      if (format.PrefersExternalSampler()) {
+        return false;
+      }
+      for (int plane = 0; plane < format.NumberOfPlanes(); plane++) {
+        if (ToVkFormat(format, plane) == VK_FORMAT_UNDEFINED) {
+          return false;
+        }
+      }
+    }
+  }
+
+  // ALPHA_8 is only used by UI and should never need GL/Vulkan interop.
+  // LUMINANCE_8 is only used with GL ES2 contexts and shouldn't be relevant for
+  // devices that support Vulkan.
+  if (format == viz::SinglePlaneFormat::kALPHA_8 ||
+      format == viz::SinglePlaneFormat::kLUMINANCE_8) {
+    return false;
+  }
+
+  return true;
 }
 
 }  // namespace
@@ -248,34 +284,10 @@
     gfx::GpuMemoryBufferType gmb_type,
     GrContextType gr_context_type,
     base::span<const uint8_t> pixel_data) {
-  if (format.is_multi_plane()) {
-    if (gmb_type != gfx::EMPTY_BUFFER && !format.PrefersExternalSampler()) {
-      return false;
-    }
-
-    if (format != viz::MultiPlaneFormat::kNV12 &&
-        format != viz::MultiPlaneFormat::kYV12 &&
-        format != viz::MultiPlaneFormat::kI420) {
-      return false;
-    }
-  }
-
-  // ALPHA_8 is only used by UI and should never need GL/Vulkan interop.
-  // LUMINANCE_8 is only used with GL ES2 contexts and shouldn't be relevant for
-  // devices that support Vulkan.
-  if (format == viz::SinglePlaneFormat::kALPHA_8 ||
-      format == viz::SinglePlaneFormat::kLUMINANCE_8) {
+  if (!IsFormatSupported(format, gmb_type)) {
     return false;
   }
 
-#if BUILDFLAG(IS_LINUX)
-  if (format.IsLegacyMultiplanar()) {
-    // ExternalVkImageBacking doesn't work properly with external sampler
-    // multi-planar formats on Linux, see https://crbug.com/1394888.
-    return false;
-  }
-#endif
-
   if (gmb_type == gfx::EMPTY_BUFFER) {
     if (usage & SHARED_IMAGE_USAGE_CPU_WRITE) {
       // Only CPU writable when the client provides a NativePixmap.
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm b/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
index 06565b7..e616904 100644
--- a/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
+++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing.mm
@@ -1123,7 +1123,7 @@
     return SkiaGraphiteDawnImageRepresentation::Create(
         std::move(dawn_representation), context_state,
         context_state->gpu_main_graphite_recorder(), manager, this, tracker,
-        static_cast<int>(io_surface_plane_), is_yuv_plane);
+        is_yuv_plane);
 #endif
   } else {
     CHECK_EQ(context_state->gr_context_type(), GrContextType::kGraphiteMetal);
diff --git a/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc b/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc
index 3b0779f..cefbb02 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc
@@ -417,8 +417,8 @@
   return wgpu::TextureFormat::Undefined;
 }
 
-wgpu::TextureFormat ToDawnFormat(viz::SharedImageFormat format,
-                                 int plane_index) {
+wgpu::TextureFormat ToDawnTextureViewFormat(viz::SharedImageFormat format,
+                                            int plane_index) {
   CHECK(format.is_multi_plane() || format.IsLegacyMultiplanar() ||
         (plane_index == 0));
   // The multi plane formats create a separate image per plane and return the
@@ -492,6 +492,11 @@
     return wgpu::TextureAspect::All;
   }
 
+  // Dawn only supports 2 plane multiplanar formats i.e. NV12 and P010.
+  if (format.plane_config() != viz::SharedImageFormat::PlaneConfig::kY_UV) {
+    return wgpu::TextureAspect::All;
+  }
+
   if (plane_index == 0) {
     return wgpu::TextureAspect::Plane0Only;
   }
@@ -533,10 +538,12 @@
     bool scanout_dcomp_surface,
     bool supports_multiplanar_rendering) {
   skgpu::graphite::DawnTextureInfo dawn_texture_info;
-  wgpu::TextureFormat wgpu_format = ToDawnFormat(format, plane_index);
+  wgpu::TextureFormat wgpu_format =
+      ToDawnTextureViewFormat(format, plane_index);
   if (wgpu_format != wgpu::TextureFormat::Undefined) {
     dawn_texture_info.fSampleCount = 1;
     dawn_texture_info.fFormat = wgpu_format;
+    dawn_texture_info.fAspect = GetDawnTextureAspect(format, plane_index);
     dawn_texture_info.fUsage = GetSupportedDawnTextureUsage(
         is_yuv_plane, scanout_dcomp_surface, supports_multiplanar_rendering);
     dawn_texture_info.fMipmapped =
diff --git a/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h b/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h
index 998eb16..d1ef3dc 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h
+++ b/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h
@@ -97,17 +97,19 @@
                                      int plane_index);
 #endif
 
-// Following functions return the appropriate WebGPU/Dawn format for a
+// Following functions return the appropriate Dawn format for a
+// SharedImageFormat. Returns wgpu::TextureFormat format for given `format`.
+// Note that this will return a multi-planar Dawn format for multi-planar
 // SharedImageFormat.
-// Returns wgpu::TextureFormat format for given `format`. Note that this will
-// return a multi-planar Dawn format for multi-planar SharedImageFormat.
 GPU_GLES2_EXPORT wgpu::TextureFormat ToDawnFormat(
     viz::SharedImageFormat format);
 // Returns wgpu::TextureFormat format for given `format` and `plane_index`. Note
-// that this returns a single plane Dawn format and not a multi-planar format.
-// `plane_index` must be 0 if `format` is single-plane.
-GPU_GLES2_EXPORT wgpu::TextureFormat ToDawnFormat(viz::SharedImageFormat format,
-                                                  int plane_index);
+// that this returns a single plane Dawn format i.e the TextureView format and
+// not a multi-planar format. `plane_index` must be 0 if `format` is
+// single-plane.
+GPU_GLES2_EXPORT wgpu::TextureFormat ToDawnTextureViewFormat(
+    viz::SharedImageFormat format,
+    int plane_index);
 
 // Returns the supported Dawn texture usage. `is_yuv_plane` indicates if the
 // texture corresponds to a plane of a multi-planar image and `is_dcomp_surface`
diff --git a/gpu/command_buffer/service/shared_image/skia_graphite_dawn_image_representation.cc b/gpu/command_buffer/service/shared_image/skia_graphite_dawn_image_representation.cc
index 622ad00..fa45560 100644
--- a/gpu/command_buffer/service/shared_image/skia_graphite_dawn_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image/skia_graphite_dawn_image_representation.cc
@@ -20,21 +20,6 @@
 namespace gpu {
 
 namespace {
-wgpu::TextureView CreatePlaneView(const wgpu::Texture& texture,
-                                  int plane_index) {
-  CHECK(texture.GetFormat() == wgpu::TextureFormat::R8BG8Biplanar420Unorm ||
-        texture.GetFormat() ==
-            wgpu::TextureFormat::R10X6BG10X6Biplanar420Unorm);
-  wgpu::TextureViewDescriptor view_desc;
-  if (plane_index == 0) {
-    view_desc.aspect = wgpu::TextureAspect::Plane0Only;
-  } else {
-    CHECK_EQ(plane_index, 1);
-    view_desc.aspect = wgpu::TextureAspect::Plane1Only;
-  }
-  return texture.CreateView(&view_desc);
-}
-
 bool SupportsMultiplanarRendering(SharedContextState* context_state) {
   auto* dawn_context_provider = context_state->dawn_context_provider();
   if (!dawn_context_provider) {
@@ -54,7 +39,6 @@
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
-    int plane_index,
     bool is_yuv_plane) {
   const bool is_dcomp_surface =
       backing->usage() & SHARED_IMAGE_USAGE_SCANOUT_DCOMP_SURFACE;
@@ -64,8 +48,7 @@
       is_yuv_plane, is_dcomp_surface, supports_multiplanar_rendering);
   return base::WrapUnique(new SkiaGraphiteDawnImageRepresentation(
       std::move(dawn_representation), recorder, std::move(context_state),
-      manager, backing, tracker, plane_index, is_yuv_plane,
-      supported_tex_usages));
+      manager, backing, tracker, is_yuv_plane, supported_tex_usages));
 }
 
 SkiaGraphiteDawnImageRepresentation::SkiaGraphiteDawnImageRepresentation(
@@ -75,14 +58,12 @@
     SharedImageManager* manager,
     SharedImageBacking* backing,
     MemoryTypeTracker* tracker,
-    int plane_index,
     bool is_yuv_plane,
     wgpu::TextureUsage supported_tex_usages)
     : SkiaGraphiteImageRepresentation(manager, backing, tracker),
       dawn_representation_(std::move(dawn_representation)),
       context_state_(std::move(context_state)),
       recorder_(recorder),
-      plane_index_(plane_index),
       is_yuv_plane_(is_yuv_plane),
       supported_tex_usages_(supported_tex_usages) {
   CHECK(dawn_representation_);
@@ -103,32 +84,26 @@
   std::vector<skgpu::graphite::BackendTexture> backend_textures;
   const bool supports_multiplanar_rendering =
       SupportsMultiplanarRendering(context_state_.get());
-  CHECK(plane_views_.empty());
   if (format() == viz::MultiPlaneFormat::kNV12 ||
       format() == viz::MultiPlaneFormat::kP010) {
     backend_textures.reserve(format().NumberOfPlanes());
-    plane_views_.reserve(format().NumberOfPlanes());
     for (int plane_index = 0; plane_index < format().NumberOfPlanes();
          plane_index++) {
-      wgpu::TextureView plane_view = CreatePlaneView(texture, plane_index);
       SkISize plane_size =
           gfx::SizeToSkISize(format().GetPlaneSize(plane_index, size()));
       skgpu::graphite::DawnTextureInfo plane_info = GetGraphiteDawnTextureInfo(
           format(), plane_index, /*is_yuv_plane=*/true, /*mipmapped=*/false,
           /*scanout_dcomp_surface=*/false, supports_multiplanar_rendering);
-      backend_textures.emplace_back(plane_size, plane_info, plane_view.Get());
-      plane_views_.push_back(std::move(plane_view));
+      backend_textures.emplace_back(plane_size, plane_info, texture.Get());
     }
   } else if (is_yuv_plane_) {
     // Legacy multi-planar NV12 - format() is either R8 or RG8.
-    wgpu::TextureView plane_view = CreatePlaneView(texture, plane_index_);
     SkISize plane_size = gfx::SizeToSkISize(size());
     skgpu::graphite::DawnTextureInfo plane_info = GetGraphiteDawnTextureInfo(
         format(), /*plane_index=*/0, /*is_yuv_plane=*/true, /*mipmapped=*/false,
         /*scanout_dcomp_surface=*/false, supports_multiplanar_rendering);
-    backend_textures = {skgpu::graphite::BackendTexture(plane_size, plane_info,
-                                                        plane_view.Get())};
-    plane_views_ = {std::move(plane_view)};
+    backend_textures = {
+        skgpu::graphite::BackendTexture(plane_size, plane_info, texture.Get())};
   } else {
     CHECK(format().is_single_plane() && !format().IsLegacyMultiplanar());
     backend_textures = {skgpu::graphite::BackendTexture(texture.Get())};
@@ -197,7 +172,6 @@
 
 void SkiaGraphiteDawnImageRepresentation::EndWriteAccess() {
   CHECK_EQ(mode_, RepresentationAccessMode::kWrite);
-  plane_views_.clear();
   dawn_scoped_access_.reset();
   mode_ = RepresentationAccessMode::kNone;
 }
@@ -220,7 +194,6 @@
 
 void SkiaGraphiteDawnImageRepresentation::EndReadAccess() {
   CHECK_EQ(mode_, RepresentationAccessMode::kRead);
-  plane_views_.clear();
   dawn_scoped_access_.reset();
   mode_ = RepresentationAccessMode::kNone;
 }
diff --git a/gpu/command_buffer/service/shared_image/skia_graphite_dawn_image_representation.h b/gpu/command_buffer/service/shared_image/skia_graphite_dawn_image_representation.h
index e25c2c7..4563a00c 100644
--- a/gpu/command_buffer/service/shared_image/skia_graphite_dawn_image_representation.h
+++ b/gpu/command_buffer/service/shared_image/skia_graphite_dawn_image_representation.h
@@ -23,7 +23,6 @@
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
-      int plane_index = 0,
       bool is_yuv_plane = false);
 
   ~SkiaGraphiteDawnImageRepresentation() override;
@@ -45,7 +44,6 @@
       SharedImageManager* manager,
       SharedImageBacking* backing,
       MemoryTypeTracker* tracker,
-      int plane_index,
       bool is_yuv_plane,
       wgpu::TextureUsage supported_tex_usages);
 
@@ -56,11 +54,9 @@
   std::unique_ptr<DawnImageRepresentation::ScopedAccess> dawn_scoped_access_;
   scoped_refptr<SharedContextState> context_state_;
   const raw_ptr<skgpu::graphite::Recorder> recorder_;
-  const int plane_index_;
   const bool is_yuv_plane_;
   const wgpu::TextureUsage supported_tex_usages_;
   RepresentationAccessMode mode_ = RepresentationAccessMode::kNone;
-  std::vector<wgpu::TextureView> plane_views_;
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_interface_in_process.cc b/gpu/command_buffer/service/shared_image_interface_in_process.cc
index b928eb9..8ef587a 100644
--- a/gpu/command_buffer/service/shared_image_interface_in_process.cc
+++ b/gpu/command_buffer/service/shared_image_interface_in_process.cc
@@ -543,7 +543,8 @@
   sync_point_client_state_->ReleaseFenceSync(sync_token.release_count());
 }
 
-Mailbox SharedImageInterfaceInProcess::CreateSharedImage(
+scoped_refptr<ClientSharedImage>
+SharedImageInterfaceInProcess::CreateSharedImage(
     gfx::GpuMemoryBuffer* gpu_memory_buffer,
     GpuMemoryBufferManager* gpu_memory_buffer_manager,
     gfx::BufferPlane plane,
@@ -578,7 +579,7 @@
         {});
   }
 
-  return mailbox;
+  return base::MakeRefCounted<ClientSharedImage>(mailbox);
 }
 
 void SharedImageInterfaceInProcess::CreateGMBSharedImageOnGpuThread(
diff --git a/gpu/command_buffer/service/shared_image_interface_in_process.h b/gpu/command_buffer/service/shared_image_interface_in_process.h
index 2bdf70d..c8d0c8b 100644
--- a/gpu/command_buffer/service/shared_image_interface_in_process.h
+++ b/gpu/command_buffer/service/shared_image_interface_in_process.h
@@ -106,14 +106,15 @@
       uint32_t usage,
       base::StringPiece debug_label,
       gfx::GpuMemoryBufferHandle buffer_handle) override;
-  Mailbox CreateSharedImage(gfx::GpuMemoryBuffer* gpu_memory_buffer,
-                            GpuMemoryBufferManager* gpu_memory_buffer_manager,
-                            gfx::BufferPlane plane,
-                            const gfx::ColorSpace& color_space,
-                            GrSurfaceOrigin surface_origin,
-                            SkAlphaType alpha_type,
-                            uint32_t usage,
-                            base::StringPiece debug_label) override;
+  scoped_refptr<ClientSharedImage> CreateSharedImage(
+      gfx::GpuMemoryBuffer* gpu_memory_buffer,
+      GpuMemoryBufferManager* gpu_memory_buffer_manager,
+      gfx::BufferPlane plane,
+      const gfx::ColorSpace& color_space,
+      GrSurfaceOrigin surface_origin,
+      SkAlphaType alpha_type,
+      uint32_t usage,
+      base::StringPiece debug_label) override;
   void UpdateSharedImage(const SyncToken& sync_token,
                          const Mailbox& mailbox) override;
   void UpdateSharedImage(const SyncToken& sync_token,
diff --git a/gpu/config/BUILD.gn b/gpu/config/BUILD.gn
index 8d1b7f4a..f4aafdfc 100644
--- a/gpu/config/BUILD.gn
+++ b/gpu/config/BUILD.gn
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/ui.gni")
 import("//gpu/vulkan/features.gni")
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index ebb0ee3..785f931 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -3661,6 +3661,7 @@
         "type": "win"
       },
       "vendor_id": "0x8086",
+      "multi_gpu_category": "any",
       "driver_version": {
         "op": "<",
         "value": "30.0.100.9667"
@@ -3677,6 +3678,7 @@
         "type": "win"
       },
       "vendor_id": "0x8086",
+      "multi_gpu_category": "any",
       "intel_gpu_generation": {
         "op": "<",
         "value": "11"
diff --git a/gpu/config/gpu_preferences_unittest.cc b/gpu/config/gpu_preferences_unittest.cc
index 9cce5826..0d69456 100644
--- a/gpu/config/gpu_preferences_unittest.cc
+++ b/gpu/config/gpu_preferences_unittest.cc
@@ -83,8 +83,6 @@
   EXPECT_EQ(left.enabled_dawn_features_list, right.enabled_dawn_features_list);
   EXPECT_EQ(left.disabled_dawn_features_list,
             right.disabled_dawn_features_list);
-  EXPECT_EQ(left.enable_gpu_blocked_time_metric,
-            right.enable_gpu_blocked_time_metric);
   EXPECT_EQ(left.enable_perf_data_collection,
             right.enable_perf_data_collection);
 #if BUILDFLAG(IS_OZONE)
@@ -177,7 +175,6 @@
     GPU_PREFERENCES_FIELD_ENUM(enable_dawn_backend_validation,
                                DawnBackendValidationLevel::kPartial,
                                mojom::DawnBackendValidationLevel::kPartial)
-    GPU_PREFERENCES_FIELD(enable_gpu_blocked_time_metric, true)
     GPU_PREFERENCES_FIELD(enable_perf_data_collection, true)
 #if BUILDFLAG(IS_OZONE)
     GPU_PREFERENCES_FIELD_ENUM(message_pump_type, base::MessagePumpType::UI,
@@ -270,7 +267,6 @@
   PRINT_BOOL(enable_gpu_benchmarking_extension);
   PRINT_BOOL(enable_webgpu);
   PRINT_INT(enable_dawn_backend_validation);
-  PRINT_BOOL(enable_gpu_blocked_time_metric);
   PRINT_BOOL(enable_perf_data_collection);
 #if BUILDFLAG(IS_OZONE)
   PRINT_INT(message_pump_type);
diff --git a/gpu/ipc/client/client_shared_image_interface.cc b/gpu/ipc/client/client_shared_image_interface.cc
index 54df6fa3..0366c14 100644
--- a/gpu/ipc/client/client_shared_image_interface.cc
+++ b/gpu/ipc/client/client_shared_image_interface.cc
@@ -159,7 +159,7 @@
           debug_label, std::move(buffer_handle))));
 }
 
-Mailbox ClientSharedImageInterface::CreateSharedImage(
+scoped_refptr<ClientSharedImage> ClientSharedImageInterface::CreateSharedImage(
     gfx::GpuMemoryBuffer* gpu_memory_buffer,
     GpuMemoryBufferManager* gpu_memory_buffer_manager,
     gfx::BufferPlane plane,
@@ -171,10 +171,11 @@
   DCHECK(gpu::IsValidClientUsage(usage)) << usage;
   auto buffer_format = gpu_memory_buffer->GetFormat();
   CHECK(gpu::IsPlaneValidForGpuMemoryBufferFormat(plane, buffer_format));
-  return AddMailbox(proxy_->CreateSharedImage(
-      buffer_format, plane, gpu_memory_buffer->GetSize(), color_space,
-      surface_origin, alpha_type, usage, debug_label,
-      gpu_memory_buffer->CloneHandle()));
+  return base::MakeRefCounted<ClientSharedImage>(
+      AddMailbox(proxy_->CreateSharedImage(
+          buffer_format, plane, gpu_memory_buffer->GetSize(), color_space,
+          surface_origin, alpha_type, usage, debug_label,
+          gpu_memory_buffer->CloneHandle())));
 }
 
 #if BUILDFLAG(IS_WIN)
diff --git a/gpu/ipc/client/client_shared_image_interface.h b/gpu/ipc/client/client_shared_image_interface.h
index e5ea435..20d3194 100644
--- a/gpu/ipc/client/client_shared_image_interface.h
+++ b/gpu/ipc/client/client_shared_image_interface.h
@@ -85,14 +85,15 @@
   // NOTE: The below method is DEPRECATED for `gpu_memory_buffer` only with
   // single planar eg. RGB BufferFormats. Please use the equivalent method above
   // taking in single planar SharedImageFormat with GpuMemoryBufferHandle.
-  Mailbox CreateSharedImage(gfx::GpuMemoryBuffer* gpu_memory_buffer,
-                            GpuMemoryBufferManager* gpu_memory_buffer_manager,
-                            gfx::BufferPlane plane,
-                            const gfx::ColorSpace& color_space,
-                            GrSurfaceOrigin surface_origin,
-                            SkAlphaType alpha_type,
-                            uint32_t usage,
-                            base::StringPiece debug_label) override;
+  scoped_refptr<ClientSharedImage> CreateSharedImage(
+      gfx::GpuMemoryBuffer* gpu_memory_buffer,
+      GpuMemoryBufferManager* gpu_memory_buffer_manager,
+      gfx::BufferPlane plane,
+      const gfx::ColorSpace& color_space,
+      GrSurfaceOrigin surface_origin,
+      SkAlphaType alpha_type,
+      uint32_t usage,
+      base::StringPiece debug_label) override;
 #if BUILDFLAG(IS_WIN)
   void CopyToGpuMemoryBuffer(const SyncToken& sync_token,
                              const Mailbox& mailbox) override;
diff --git a/gpu/ipc/common/gpu_preferences.mojom b/gpu/ipc/common/gpu_preferences.mojom
index 5a5eb4a5..260e452f 100644
--- a/gpu/ipc/common/gpu_preferences.mojom
+++ b/gpu/ipc/common/gpu_preferences.mojom
@@ -110,7 +110,6 @@
   DawnBackendValidationLevel enable_dawn_backend_validation;
   array<string> enabled_dawn_features_list;
   array<string> disabled_dawn_features_list;
-  bool enable_gpu_blocked_time_metric;
   bool enable_perf_data_collection;
 
   [EnableIf=use_ozone]
diff --git a/gpu/ipc/common/gpu_preferences_mojom_traits.h b/gpu/ipc/common/gpu_preferences_mojom_traits.h
index 64251f88..943c945 100644
--- a/gpu/ipc/common/gpu_preferences_mojom_traits.h
+++ b/gpu/ipc/common/gpu_preferences_mojom_traits.h
@@ -304,8 +304,6 @@
     if (!prefs.ReadDisabledDawnFeaturesList(&out->disabled_dawn_features_list))
       return false;
 
-    out->enable_gpu_blocked_time_metric =
-        prefs.enable_gpu_blocked_time_metric();
     out->enable_perf_data_collection = prefs.enable_perf_data_collection();
 
 #if BUILDFLAG(IS_OZONE)
@@ -501,9 +499,6 @@
       const gpu::GpuPreferences& prefs) {
     return prefs.disabled_dawn_features_list;
   }
-  static bool enable_gpu_blocked_time_metric(const gpu::GpuPreferences& prefs) {
-    return prefs.enable_gpu_blocked_time_metric;
-  }
   static bool enable_perf_data_collection(const gpu::GpuPreferences& prefs) {
     return prefs.enable_perf_data_collection;
   }
diff --git a/gpu/ipc/service/gles2_command_buffer_stub.cc b/gpu/ipc/service/gles2_command_buffer_stub.cc
index c8a3b64..3873d72 100644
--- a/gpu/ipc/service/gles2_command_buffer_stub.cc
+++ b/gpu/ipc/service/gles2_command_buffer_stub.cc
@@ -419,10 +419,6 @@
   return viz::GpuVSyncCallback();
 }
 
-base::TimeDelta GLES2CommandBufferStub::GetGpuBlockedTimeSinceLastSwap() {
-  return channel_->scheduler()->TakeTotalBlockingTime();
-}
-
 MemoryTracker* GLES2CommandBufferStub::GetContextGroupMemoryTracker() const {
   return context_group_->memory_tracker();
 }
diff --git a/gpu/ipc/service/gles2_command_buffer_stub.h b/gpu/ipc/service/gles2_command_buffer_stub.h
index 06aee3d..c2a1231 100644
--- a/gpu/ipc/service/gles2_command_buffer_stub.h
+++ b/gpu/ipc/service/gles2_command_buffer_stub.h
@@ -53,7 +53,6 @@
   const gles2::FeatureInfo* GetFeatureInfo() const override;
   const GpuPreferences& GetGpuPreferences() const override;
   viz::GpuVSyncCallback GetGpuVSyncCallback() override;
-  base::TimeDelta GetGpuBlockedTimeSinceLastSwap() override;
 
  private:
   // CommandBufferStub overrides:
diff --git a/gpu/ipc/service/image_transport_surface_delegate.h b/gpu/ipc/service/image_transport_surface_delegate.h
index 3631e53..5cc09ea0 100644
--- a/gpu/ipc/service/image_transport_surface_delegate.h
+++ b/gpu/ipc/service/image_transport_surface_delegate.h
@@ -35,9 +35,6 @@
   // Callback for GPU vsync signal.  May be called on a different thread.
   virtual viz::GpuVSyncCallback GetGpuVSyncCallback() = 0;
 
-  // Returns how long GpuThread was blocked since last swap. Used for metrics.
-  virtual base::TimeDelta GetGpuBlockedTimeSinceLastSwap() = 0;
-
  protected:
   virtual ~ImageTransportSurfaceDelegate() = default;
 };
diff --git a/gpu/ipc/service/pass_through_image_transport_surface.cc b/gpu/ipc/service/pass_through_image_transport_surface.cc
index 7b604753..6f3ac82 100644
--- a/gpu/ipc/service/pass_through_image_transport_surface.cc
+++ b/gpu/ipc/service/pass_through_image_transport_surface.cc
@@ -50,15 +50,13 @@
 gfx::SwapResult PassThroughImageTransportSurface::SwapBuffers(
     PresentationCallback callback,
     gfx::FrameData data) {
-  gfx::SwapResponse response;
-  StartSwapBuffers(&response);
+  StartSwapBuffers();
   gfx::SwapResult result = gl::GLSurfaceAdapter::SwapBuffers(
       base::BindOnce(&PassThroughImageTransportSurface::BufferPresented,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback),
                      local_swap_id_),
       data);
-  response.result = result;
-  FinishSwapBuffers(std::move(response), local_swap_id_,
+  FinishSwapBuffers(local_swap_id_,
                     /*release_fence=*/gfx::GpuFenceHandle());
   return result;
 }
@@ -67,8 +65,7 @@
     SwapCompletionCallback completion_callback,
     PresentationCallback presentation_callback,
     gfx::FrameData data) {
-  gfx::SwapResponse response;
-  StartSwapBuffers(&response);
+  StartSwapBuffers();
 
   // We use WeakPtr here to avoid manual management of life time of an instance
   // of this class. Callback will not be called once the instance of this class
@@ -77,7 +74,7 @@
   gl::GLSurfaceAdapter::SwapBuffersAsync(
       base::BindOnce(&PassThroughImageTransportSurface::FinishSwapBuffersAsync,
                      weak_ptr_factory_.GetWeakPtr(),
-                     std::move(completion_callback), response, local_swap_id_),
+                     std::move(completion_callback), local_swap_id_),
       base::BindOnce(&PassThroughImageTransportSurface::BufferPresented,
                      weak_ptr_factory_.GetWeakPtr(),
                      std::move(presentation_callback), local_swap_id_),
@@ -88,16 +85,14 @@
     const std::vector<gfx::Rect>& rects,
     PresentationCallback callback,
     gfx::FrameData data) {
-  gfx::SwapResponse response;
-  StartSwapBuffers(&response);
+  StartSwapBuffers();
   gfx::SwapResult result = gl::GLSurfaceAdapter::SwapBuffersWithBounds(
       rects,
       base::BindOnce(&PassThroughImageTransportSurface::BufferPresented,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback),
                      local_swap_id_),
       data);
-  response.result = result;
-  FinishSwapBuffers(response, local_swap_id_,
+  FinishSwapBuffers(local_swap_id_,
                     /*release_fence=*/gfx::GpuFenceHandle());
   return result;
 }
@@ -109,16 +104,14 @@
     int height,
     PresentationCallback callback,
     gfx::FrameData data) {
-  gfx::SwapResponse response;
-  StartSwapBuffers(&response);
+  StartSwapBuffers();
   gfx::SwapResult result = gl::GLSurfaceAdapter::PostSubBuffer(
       x, y, width, height,
       base::BindOnce(&PassThroughImageTransportSurface::BufferPresented,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback),
                      local_swap_id_),
       data);
-  response.result = result;
-  FinishSwapBuffers(response, local_swap_id_,
+  FinishSwapBuffers(local_swap_id_,
                     /*release_fence=*/gfx::GpuFenceHandle());
 
   return result;
@@ -132,13 +125,12 @@
     SwapCompletionCallback completion_callback,
     PresentationCallback presentation_callback,
     gfx::FrameData data) {
-  gfx::SwapResponse response;
-  StartSwapBuffers(&response);
+  StartSwapBuffers();
   gl::GLSurfaceAdapter::PostSubBufferAsync(
       x, y, width, height,
       base::BindOnce(&PassThroughImageTransportSurface::FinishSwapBuffersAsync,
                      weak_ptr_factory_.GetWeakPtr(),
-                     std::move(completion_callback), response, local_swap_id_),
+                     std::move(completion_callback), local_swap_id_),
       base::BindOnce(&PassThroughImageTransportSurface::BufferPresented,
                      weak_ptr_factory_.GetWeakPtr(),
                      std::move(presentation_callback), local_swap_id_),
@@ -188,8 +180,7 @@
   SetVSyncEnabled(!should_override_vsync);
 }
 
-void PassThroughImageTransportSurface::StartSwapBuffers(
-    gfx::SwapResponse* response) {
+void PassThroughImageTransportSurface::StartSwapBuffers() {
   TrackMultiSurfaceSwap();
   UpdateVSyncEnabled();
 
@@ -198,18 +189,11 @@
   // before this swap is completed.
   pending_local_swap_ids_.push(++local_swap_id_);
 #endif
-  // Correct id will be populated later in the DecoderClient, before passing to
-  // client.
-  response->swap_id = 0;
-
-  response->timings.swap_start = base::TimeTicks::Now();
 }
 
 void PassThroughImageTransportSurface::FinishSwapBuffers(
-    gfx::SwapResponse response,
     uint64_t local_swap_id,
     gfx::GpuFenceHandle release_fence) {
-  response.timings.swap_end = base::TimeTicks::Now();
 
 #if DCHECK_IS_ON()
   // After the swap is completed, the local swap id is removed from the queue,
@@ -217,43 +201,13 @@
   DCHECK_EQ(pending_local_swap_ids_.front(), local_swap_id);
   pending_local_swap_ids_.pop();
 #endif
-
-  if (delegate_) {
-    auto blocked_time_since_last_swap =
-        delegate_->GetGpuBlockedTimeSinceLastSwap();
-
-    if (!multiple_surfaces_swapped_) {
-      static constexpr base::TimeDelta kTimingMetricsHistogramMin =
-          base::Microseconds(5);
-      static constexpr base::TimeDelta kTimingMetricsHistogramMax =
-          base::Milliseconds(500);
-      static constexpr uint32_t kTimingMetricsHistogramBuckets = 50;
-
-      base::TimeDelta delta =
-          response.timings.swap_end - response.timings.swap_start;
-      UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
-          "GPU.SwapTimeUs", delta, kTimingMetricsHistogramMin,
-          kTimingMetricsHistogramMax, kTimingMetricsHistogramBuckets);
-
-      // Report only if collection is enabled and supported on current platform
-      // See gpu::Scheduler::TakeTotalBlockingTime for details.
-      if (!blocked_time_since_last_swap.is_min()) {
-        LOCAL_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
-            "GPU.GpuBlockedBetweenSwapsUs2", blocked_time_since_last_swap,
-            kTimingMetricsHistogramMin, kTimingMetricsHistogramMax,
-            kTimingMetricsHistogramBuckets);
-      }
-    }
-  }
 }
 
 void PassThroughImageTransportSurface::FinishSwapBuffersAsync(
     SwapCompletionCallback callback,
-    gfx::SwapResponse response,
     uint64_t local_swap_id,
     gfx::SwapCompletionResult result) {
-  response.result = result.swap_result;
-  FinishSwapBuffers(response, local_swap_id, result.release_fence.Clone());
+  FinishSwapBuffers(local_swap_id, result.release_fence.Clone());
   std::move(callback).Run(std::move(result));
 }
 
diff --git a/gpu/ipc/service/pass_through_image_transport_surface.h b/gpu/ipc/service/pass_through_image_transport_surface.h
index c039c8a0..6c54f32 100644
--- a/gpu/ipc/service/pass_through_image_transport_surface.h
+++ b/gpu/ipc/service/pass_through_image_transport_surface.h
@@ -63,12 +63,10 @@
   void TrackMultiSurfaceSwap();
   void UpdateVSyncEnabled();
 
-  void StartSwapBuffers(gfx::SwapResponse* response);
-  void FinishSwapBuffers(gfx::SwapResponse response,
-                         uint64_t local_swap_id,
+  void StartSwapBuffers();
+  void FinishSwapBuffers(uint64_t local_swap_id,
                          gfx::GpuFenceHandle release_fence);
   void FinishSwapBuffersAsync(SwapCompletionCallback callback,
-                              gfx::SwapResponse response,
                               uint64_t local_swap_id,
                               gfx::SwapCompletionResult result);
 
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 1f75b1a..2188046 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -63681,6 +63681,10 @@
         value: 10
       }
       experiments {
+        key: "chromium.compilator_can_outlive_parent"
+        value: 100
+      }
+      experiments {
         key: "chromium_swarming.expose_merge_script_failures"
         value: 100
       }
@@ -98936,7 +98940,7 @@
       name: "win-rel-compilator"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:win-rel-compilator"
-      dimensions: "cores:16"
+      dimensions: "cores:16|32"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows-10"
       dimensions: "pool:luci.chromium.try"
diff --git a/infra/config/generated/luci/luci-analysis-dev.cfg b/infra/config/generated/luci/luci-analysis-dev.cfg
index e3708dbb..40b5ad80 100644
--- a/infra/config/generated/luci/luci-analysis-dev.cfg
+++ b/infra/config/generated/luci/luci-analysis-dev.cfg
@@ -170,7 +170,7 @@
         one_day: 10
       }
       deactivation_threshold {
-        one_day: 1
+        one_day: 3
       }
     }
     explanation {
diff --git a/infra/config/generated/luci/luci-analysis.cfg b/infra/config/generated/luci/luci-analysis.cfg
index 4f4f7f9..80902f1 100644
--- a/infra/config/generated/luci/luci-analysis.cfg
+++ b/infra/config/generated/luci/luci-analysis.cfg
@@ -171,7 +171,7 @@
         one_day: 10
       }
       deactivation_threshold {
-        one_day: 1
+        one_day: 3
       }
     }
     explanation {
diff --git a/infra/config/generated/testing/test_suites.pyl b/infra/config/generated/testing/test_suites.pyl
index de56ff73..f0f25e3 100644
--- a/infra/config/generated/testing/test_suites.pyl
+++ b/infra/config/generated/testing/test_suites.pyl
@@ -4102,6 +4102,19 @@
       },
     },
 
+    'lacros_skylab_tests_version_skew': {
+      'lacros_all_tast_tests': {
+        'tast_expr': '("group:mainline" && ("dep:lacros_stable" || "dep:lacros") && !informational)',
+        'test_level_retries': 2,
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'timeout_sec': 10800,
+        'shards': 2,
+        'experiment_percentage': 100,
+      },
+    },
+
     'lacros_skylab_tests_with_gtests': {
       'chromeos_integration_tests': {},
     },
@@ -7494,30 +7507,34 @@
     },
 
     'lacros_skylab_tests_amd64_generic': {
-      'lacros_skylab_tests': {
+      'lacros_skylab_tests_version_skew': {
         'variants': [
-          'CROS_BRYA_RELEASE_LKGM',
           'CROS_BRYA_RELEASE_DEV',
           'CROS_BRYA_RELEASE_BETA',
           'CROS_BRYA_RELEASE_STABLE',
-          'CROS_DEDEDE_RELEASE_LKGM',
           'CROS_DEDEDE_RELEASE_DEV',
           'CROS_DEDEDE_RELEASE_BETA',
           'CROS_DEDEDE_RELEASE_STABLE',
-          'CROS_FIZZ_RELEASE_LKGM',
           'CROS_FIZZ_RELEASE_DEV',
           'CROS_FIZZ_RELEASE_BETA',
           'CROS_FIZZ_RELEASE_STABLE',
-          'CROS_GUYBRUSH_RELEASE_LKGM',
           'CROS_GUYBRUSH_RELEASE_DEV',
           'CROS_GUYBRUSH_RELEASE_BETA',
           'CROS_GUYBRUSH_RELEASE_STABLE',
-          'CROS_PUFF_RELEASE_LKGM',
           'CROS_PUFF_RELEASE_DEV',
           'CROS_PUFF_RELEASE_BETA',
           'CROS_PUFF_RELEASE_STABLE',
         ],
       },
+      'lacros_skylab_tests': {
+        'variants': [
+          'CROS_BRYA_RELEASE_LKGM',
+          'CROS_DEDEDE_RELEASE_LKGM',
+          'CROS_FIZZ_RELEASE_LKGM',
+          'CROS_GUYBRUSH_RELEASE_LKGM',
+          'CROS_PUFF_RELEASE_LKGM',
+        ],
+      },
       'lacros_skylab_tests_with_gtests': {
         'variants': [
           'CROS_BRYA_RELEASE_LKGM',
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl
index ce69e6ec4..f47dcc27 100644
--- a/infra/config/generated/testing/variants.pyl
+++ b/infra/config/generated/testing/variants.pyl
@@ -70,32 +70,32 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 121.0.6110.0',
+    'description': 'Run with ash-chrome version 121.0.6111.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6110.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v121.0.6110.0',
-          'revision': 'version:121.0.6110.0',
+          'location': 'lacros_version_skew_tests_v121.0.6111.0',
+          'revision': 'version:121.0.6111.0',
         },
       ],
     },
   },
   'LACROS_VERSION_SKEW_DEV': {
     'identifier': 'Lacros version skew testing ash dev',
-    'description': 'Run with ash-chrome version 120.0.6085.0',
+    'description': 'Run with ash-chrome version 120.0.6099.8',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6085.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v120.0.6085.0',
-          'revision': 'version:120.0.6085.0',
+          'location': 'lacros_version_skew_tests_v120.0.6099.8',
+          'revision': 'version:120.0.6099.8',
         },
       ],
     },
diff --git a/infra/config/luci-analysis-dev.cfg b/infra/config/luci-analysis-dev.cfg
index e3708dbb..40b5ad80 100644
--- a/infra/config/luci-analysis-dev.cfg
+++ b/infra/config/luci-analysis-dev.cfg
@@ -170,7 +170,7 @@
         one_day: 10
       }
       deactivation_threshold {
-        one_day: 1
+        one_day: 3
       }
     }
     explanation {
diff --git a/infra/config/luci-analysis.cfg b/infra/config/luci-analysis.cfg
index 4f4f7f9..80902f1 100644
--- a/infra/config/luci-analysis.cfg
+++ b/infra/config/luci-analysis.cfg
@@ -171,7 +171,7 @@
         one_day: 10
       }
       deactivation_threshold {
-        one_day: 1
+        one_day: 3
       }
     }
     explanation {
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
index f8b1051..6e81436 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
@@ -150,6 +150,7 @@
     experiments = {
         # go/nplus1shardsproposal
         "chromium.add_one_test_shard": 10,
+        "chromium.compilator_can_outlive_parent": 100,
     },
     main_list_view = "try",
     tryjob = try_.job(),
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.win.star b/infra/config/subprojects/chromium/try/tryserver.chromium.win.star
index c0d1f11..470b238 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.win.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.win.star
@@ -107,6 +107,8 @@
 try_.compilator_builder(
     name = "win-rel-compilator",
     branch_selector = branches.selector.WINDOWS_BRANCHES,
+    # TODO(b/309482810): Change to 32 once bots have landed
+    cores = "16|32",
     # TODO (crbug.com/1245171): Revert when root issue is fixed
     grace_period = 4 * time.minute,
     main_list_view = "try",
diff --git a/infra/config/targets/basic_suites.star b/infra/config/targets/basic_suites.star
index 6287d87c7..8107ce69 100644
--- a/infra/config/targets/basic_suites.star
+++ b/infra/config/targets/basic_suites.star
@@ -4811,6 +4811,26 @@
     },
 )
 
+# This target should usually be the same as `lacros_skylab_tests`. We use
+# a different target for version skew so we can easily disable all version skew
+# tests during an outage.
+targets.legacy_basic_suite(
+    name = "lacros_skylab_tests_version_skew",
+    tests = {
+        "lacros_all_tast_tests": targets.legacy_test_config(
+            tast_expr = "(\"group:mainline\" && (\"dep:lacros_stable\" || \"dep:lacros\") && !informational)",
+            test_level_retries = 2,
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            timeout_sec = 10800,
+            # TODO(crbug.com/1499803) re-enable when we have the required OS versions.
+            experiment_percentage = 100,
+            shards = 2,
+        ),
+    },
+)
+
 targets.legacy_basic_suite(
     name = "lacros_skylab_tests_with_gtests",
     tests = {
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json
index 045b48dc..0ca97b4d 100644
--- a/infra/config/targets/lacros-version-skew-variants.json
+++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -1,32 +1,32 @@
 {
   "LACROS_VERSION_SKEW_CANARY": {
     "args": [
-      "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6110.0/test_ash_chrome"
+      "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome"
     ],
-    "description": "Run with ash-chrome version 121.0.6110.0",
+    "description": "Run with ash-chrome version 121.0.6111.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_v121.0.6110.0",
-          "revision": "version:121.0.6110.0"
+          "location": "lacros_version_skew_tests_v121.0.6111.0",
+          "revision": "version:121.0.6111.0"
         }
       ]
     }
   },
   "LACROS_VERSION_SKEW_DEV": {
     "args": [
-      "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6085.0/test_ash_chrome"
+      "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome"
     ],
-    "description": "Run with ash-chrome version 120.0.6085.0",
+    "description": "Run with ash-chrome version 120.0.6099.8",
     "identifier": "Lacros version skew testing ash dev",
     "swarming": {
       "cipd_packages": [
         {
           "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-          "location": "lacros_version_skew_tests_v120.0.6085.0",
-          "revision": "version:120.0.6085.0"
+          "location": "lacros_version_skew_tests_v120.0.6099.8",
+          "revision": "version:120.0.6099.8"
         }
       ]
     }
diff --git a/infra/config/targets/matrix_compound_suites.star b/infra/config/targets/matrix_compound_suites.star
index 6fe86728..221f5850 100644
--- a/infra/config/targets/matrix_compound_suites.star
+++ b/infra/config/targets/matrix_compound_suites.star
@@ -1045,30 +1045,34 @@
 targets.legacy_matrix_compound_suite(
     name = "lacros_skylab_tests_amd64_generic",
     basic_suites = {
-        "lacros_skylab_tests": targets.legacy_matrix_config(
+        "lacros_skylab_tests_version_skew": targets.legacy_matrix_config(
             variants = [
-                "CROS_BRYA_RELEASE_LKGM",
                 "CROS_BRYA_RELEASE_DEV",
                 "CROS_BRYA_RELEASE_BETA",
                 "CROS_BRYA_RELEASE_STABLE",
-                "CROS_DEDEDE_RELEASE_LKGM",
                 "CROS_DEDEDE_RELEASE_DEV",
                 "CROS_DEDEDE_RELEASE_BETA",
                 "CROS_DEDEDE_RELEASE_STABLE",
-                "CROS_FIZZ_RELEASE_LKGM",
                 "CROS_FIZZ_RELEASE_DEV",
                 "CROS_FIZZ_RELEASE_BETA",
                 "CROS_FIZZ_RELEASE_STABLE",
-                "CROS_GUYBRUSH_RELEASE_LKGM",
                 "CROS_GUYBRUSH_RELEASE_DEV",
                 "CROS_GUYBRUSH_RELEASE_BETA",
                 "CROS_GUYBRUSH_RELEASE_STABLE",
-                "CROS_PUFF_RELEASE_LKGM",
                 "CROS_PUFF_RELEASE_DEV",
                 "CROS_PUFF_RELEASE_BETA",
                 "CROS_PUFF_RELEASE_STABLE",
             ],
         ),
+        "lacros_skylab_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_BRYA_RELEASE_LKGM",
+                "CROS_DEDEDE_RELEASE_LKGM",
+                "CROS_FIZZ_RELEASE_LKGM",
+                "CROS_GUYBRUSH_RELEASE_LKGM",
+                "CROS_PUFF_RELEASE_LKGM",
+            ],
+        ),
         "lacros_skylab_tests_with_gtests": targets.legacy_matrix_config(
             variants = [
                 "CROS_BRYA_RELEASE_LKGM",
diff --git a/internal b/internal
index 18eb78e..d03e9b6 160000
--- a/internal
+++ b/internal
@@ -1 +1 @@
-Subproject commit 18eb78e3ff000e59a4071961b8049610345f59a8
+Subproject commit d03e9b687fa3fb8a7deb59711777a7947b21252c
diff --git a/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_coordinator.mm b/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_coordinator.mm
index fd0d6d4..293c6a6 100644
--- a/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_coordinator.mm
+++ b/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_coordinator.mm
@@ -89,9 +89,12 @@
 
   self.viewController.parentViewControllerHeight =
       self.baseViewController.view.frame.size.height;
+  __weak __typeof(self) weakSelf = self;
   [self.baseViewController presentViewController:self.viewController
                                         animated:YES
-                                      completion:nil];
+                                      completion:^{
+                                        [weakSelf setInitialVoiceOverFocus];
+                                      }];
 }
 
 - (void)stop {
@@ -173,4 +176,9 @@
   [self.mediator disconnect];
 }
 
+- (void)setInitialVoiceOverFocus {
+  UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
+                                  self.viewController.image);
+}
+
 @end
diff --git a/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_view_controller.mm b/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_view_controller.mm
index b1a3ac3..ca3edd1 100644
--- a/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_view_controller.mm
+++ b/ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_view_controller.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/ui/autofill/bottom_sheet/payments_suggestion_bottom_sheet_view_controller.h"
 
 #import "base/metrics/histogram_functions.h"
+#import "base/strings/sys_string_conversions.h"
 #import "build/branding_buildflags.h"
 #import "components/autofill/core/browser/data_model/credit_card.h"
 #import "components/grit/components_scaled_resources.h"
@@ -108,6 +109,7 @@
   // minimized bottom sheet.
   _tableViewIsMinimized = _creditCardData.count > 2;
 
+  self.view.accessibilityViewIsModal = YES;
   self.image = [self titleImage];
   self.imageViewAccessibilityLabel = [NSString
       stringWithFormat:@"%@. %@",
@@ -144,6 +146,12 @@
   [self selectFirstRow];
 }
 
+- (void)viewDidAppear:(BOOL)animated {
+  [super viewDidAppear:animated];
+  UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
+                                  self.imageViewAccessibilityLabel);
+}
+
 - (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {
   [super traitCollectionDidChange:previousTraitCollection];
 
@@ -169,6 +177,7 @@
 }
 
 - (void)viewDidDisappear:(BOOL)animated {
+  [super viewDidDisappear:animated];
   if (self.disableBottomSheetOnExit) {
     [self.delegate disableBottomSheet];
   }
@@ -331,7 +340,11 @@
 
 // Returns an accessible card name at a given row in the table view.
 - (NSString*)accessibleCardNameAtRow:(NSInteger)row {
-  return [_creditCardData[row] accessibleCardName];
+  return l10n_util::GetNSStringF(
+      IDS_IOS_AUTOFILL_ACCNAME_SUGGESTION,
+      base::SysNSStringToUTF16([_creditCardData[row] accessibleCardName]), u"",
+      base::NumberToString16(row + 1),
+      base::NumberToString16(_creditCardData.count));
 }
 
 // Creates the payments bottom sheet's table view.
@@ -537,6 +550,7 @@
   cell.customAccessibilityLabel = [self accessibleCardNameAtRow:indexPath.row];
 
   cell.textLabel.text = [self suggestionAtRow:indexPath.row];
+  cell.accessibilityIdentifier = cell.textLabel.text;
   [cell setDetailText:[self descriptionAtRow:indexPath.row]];
   [cell setIconImage:[self iconAtRow:indexPath.row]
             tintColor:nil
diff --git a/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_keyboard_accessory_view.mm b/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_keyboard_accessory_view.mm
index 602b4ff..030a2590 100644
--- a/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_keyboard_accessory_view.mm
+++ b/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_keyboard_accessory_view.mm
@@ -165,57 +165,40 @@
 - (UIView*)shortcutButtonWithTitle:(NSString*)title {
   const CGFloat kHorizontalEdgeInset = 8;
   const CGFloat kButtonTitleFontSize = 16.0;
-  UIColor* kTitleColorStateNormal = [UIColor colorWithWhite:0.0 alpha:1.0];
   UIColor* kTitleColorStateHighlighted = [UIColor colorWithWhite:0.0 alpha:0.3];
 
   UIButton* button =
       [ExtendedTouchTargetButton buttonWithType:UIButtonTypeCustom];
+  UIButtonConfiguration* buttonConfiguration =
+      [UIButtonConfiguration plainButtonConfiguration];
+  buttonConfiguration.contentInsets = NSDirectionalEdgeInsetsMake(
+      0, kHorizontalEdgeInset, 0, kHorizontalEdgeInset);
+  UIFont* font = [UIFont systemFontOfSize:kButtonTitleFontSize
+                                   weight:UIFontWeightMedium];
+  NSAttributedString* attributedTitle =
+      [[NSAttributedString alloc] initWithString:title
+                                      attributes:@{NSFontAttributeName : font}];
+  buttonConfiguration.attributedTitle = attributedTitle;
+  buttonConfiguration.baseForegroundColor =
+      [UIColor colorNamed:kTextPrimaryColor];
+  button.configuration = buttonConfiguration;
+  button.configurationUpdateHandler = ^(UIButton* incomingButton) {
+    UIButtonConfiguration* updatedConfig = incomingButton.configuration;
+    switch (incomingButton.state) {
+      case UIControlStateHighlighted:
+        updatedConfig.baseForegroundColor = kTitleColorStateHighlighted;
+        break;
+      case UIControlStateNormal:
+        updatedConfig.baseForegroundColor =
+            [UIColor colorNamed:kTextPrimaryColor];
+        break;
+      default:
+        break;
+    }
+    incomingButton.configuration = updatedConfig;
+  };
 
-  if (IsUIButtonConfigurationEnabled()) {
-    UIButtonConfiguration* buttonConfiguration =
-        [UIButtonConfiguration plainButtonConfiguration];
-    buttonConfiguration.contentInsets = NSDirectionalEdgeInsetsMake(
-        0, kHorizontalEdgeInset, 0, kHorizontalEdgeInset);
-    UIFont* font = [UIFont systemFontOfSize:kButtonTitleFontSize
-                                     weight:UIFontWeightMedium];
-    NSAttributedString* attributedTitle = [[NSAttributedString alloc]
-        initWithString:title
-            attributes:@{NSFontAttributeName : font}];
-    buttonConfiguration.attributedTitle = attributedTitle;
-    buttonConfiguration.baseForegroundColor =
-        [UIColor colorNamed:kTextPrimaryColor];
-    button.configuration = buttonConfiguration;
-    button.configurationUpdateHandler = ^(UIButton* incomingButton) {
-      UIButtonConfiguration* updatedConfig = incomingButton.configuration;
-      switch (incomingButton.state) {
-        case UIControlStateHighlighted:
-          updatedConfig.baseForegroundColor = kTitleColorStateHighlighted;
-          break;
-        case UIControlStateNormal:
-          updatedConfig.baseForegroundColor =
-              [UIColor colorNamed:kTextPrimaryColor];
-          break;
-        default:
-          break;
-      }
-      incomingButton.configuration = updatedConfig;
-    };
-  } else {
-    [button setTitleColor:kTitleColorStateNormal forState:UIControlStateNormal];
-    [button setTitleColor:kTitleColorStateHighlighted
-                 forState:UIControlStateHighlighted];
-
-    [button setTitle:title forState:UIControlStateNormal];
-    [button setTitleColor:[UIColor colorNamed:kTextPrimaryColor]
-                 forState:UIControlStateNormal];
-    UIEdgeInsets contentEdgeInsets =
-        UIEdgeInsetsMake(0, kHorizontalEdgeInset, 0, kHorizontalEdgeInset);
-    SetContentEdgeInsets(button, contentEdgeInsets);
-    [button.titleLabel setFont:[UIFont systemFontOfSize:kButtonTitleFontSize
-                                                 weight:UIFontWeightMedium]];
-  }
   button.clipsToBounds = YES;
-
   [button addTarget:self
                 action:@selector(keyboardButtonPressed:)
       forControlEvents:UIControlEventTouchUpInside];
@@ -231,11 +214,7 @@
 - (void)keyboardButtonPressed:(id)sender {
   UIButton* button = base::apple::ObjCCastStrict<UIButton>(sender);
   [[UIDevice currentDevice] playInputClick];
-  if (IsUIButtonConfigurationEnabled()) {
-    [_delegate keyPressed:button.configuration.title];
-  } else {
-    [_delegate keyPressed:[button currentTitle]];
-  }
+  [_delegate keyPressed:button.configuration.title];
 }
 
 - (void)didMoveToWindow {
diff --git a/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_coordinator.mm b/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_coordinator.mm
index d74ecf8..2192353 100644
--- a/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_coordinator.mm
+++ b/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_coordinator.mm
@@ -101,9 +101,12 @@
     return;
   }
 
+  __weak __typeof(self) weakSelf = self;
   [self.baseViewController presentViewController:self.viewController
                                         animated:YES
-                                      completion:nil];
+                                      completion:^{
+                                        [weakSelf setInitialVoiceOverFocus];
+                                      }];
 }
 
 - (void)stop {
@@ -150,4 +153,11 @@
   // TODO(crbug.com/1422344): Add metric for when the credential is nil.
 }
 
+#pragma mark - Private
+
+- (void)setInitialVoiceOverFocus {
+  UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
+                                  self.viewController.aboveTitleView);
+}
+
 @end
diff --git a/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_view_controller.mm b/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_view_controller.mm
index 2ab117a..9eeefbbf 100644
--- a/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_view_controller.mm
+++ b/ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_view_controller.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/ui/passwords/bottom_sheet/password_suggestion_bottom_sheet_view_controller.h"
 
 #import "base/apple/foundation_util.h"
+#import "base/strings/sys_string_conversions.h"
 #import "components/autofill/ios/browser/form_suggestion.h"
 #import "components/password_manager/core/browser/ui/credential_ui_entry.h"
 #import "components/password_manager/ios/shared_password_controller.h"
@@ -89,6 +90,7 @@
 - (void)viewDidLoad {
   _tableViewIsMinimized = YES;
 
+  self.view.accessibilityViewIsModal = YES;
   self.aboveTitleView = [self setUpTitleView];
   self.customSpacing = kSpacingAfterTitle;
   self.customSpacingBeforeImageIfNoNavigationBar = kSpacingBeforeTitle;
@@ -154,6 +156,12 @@
   [self updateHeightConstraints];
 }
 
+- (void)viewDidAppear:(BOOL)animated {
+  [super viewDidAppear:animated];
+  UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
+                                  self.aboveTitleView.accessibilityLabel);
+}
+
 - (void)viewWillDisappear:(BOOL)animated {
   [self.delegate dismiss];
 }
@@ -491,6 +499,12 @@
   cell.URLLabel.text = _domain;
   cell.URLLabel.lineBreakMode = NSLineBreakByTruncatingMiddle;
   cell.URLLabel.hidden = NO;
+  cell.accessibilityLabel =
+      l10n_util::GetNSStringF(IDS_IOS_AUTOFILL_ACCNAME_SUGGESTION,
+                              base::SysNSStringToUTF16(cell.titleLabel.text),
+                              base::SysNSStringToUTF16(_domain),
+                              base::NumberToString16(indexPath.row + 1),
+                              base::NumberToString16(_suggestions.count));
 
   cell.userInteractionEnabled = YES;
 
diff --git a/ios_internal b/ios_internal
index e93c9eb..1be9791 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit e93c9eb21e418da5953bd8239704c166ee419d57
+Subproject commit 1be9791237c4cd9def25d4b0276868f05aae5ba6
diff --git a/media/BUILD.gn b/media/BUILD.gn
index e552f1f..7aba277 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -5,7 +5,7 @@
 import("//build/buildflag_header.gni")
 import("//build/config/android/config.gni")
 import("//build/config/arm.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/features.gni")
 import("//build/config/linux/pkg_config.gni")
 import("//build/config/ui.gni")
diff --git a/media/base/mac/channel_layout_util_mac.cc b/media/base/mac/channel_layout_util_mac.cc
index 3cd390d..e1b18ff7 100644
--- a/media/base/mac/channel_layout_util_mac.cc
+++ b/media/base/mac/channel_layout_util_mac.cc
@@ -109,13 +109,9 @@
       new_layout->layout()->mChannelDescriptions;
 
   if (input_layout == CHANNEL_LAYOUT_DISCRETE) {
-    // For the discrete case just assume common input mappings; once we run out
-    // of known channels mark them as unknown.
+    // For the discrete case, mark all channels as unknown.
     for (int ch = 0; ch < input_channels; ++ch) {
-      descriptions[ch].mChannelLabel =
-          ch > CHANNELS_MAX
-              ? kAudioChannelLabel_Unknown
-              : ChannelToAudioChannelLabel(static_cast<Channels>(ch));
+      descriptions[ch].mChannelLabel = kAudioChannelLabel_Unknown;
       descriptions[ch].mChannelFlags = kAudioChannelFlags_AllOff;
     }
   } else if (input_layout == CHANNEL_LAYOUT_MONO) {
diff --git a/media/base/mac/channel_layout_util_mac_unittests.cc b/media/base/mac/channel_layout_util_mac_unittests.cc
index fc9ba34..46ea6fa 100644
--- a/media/base/mac/channel_layout_util_mac_unittests.cc
+++ b/media/base/mac/channel_layout_util_mac_unittests.cc
@@ -118,54 +118,12 @@
             kAudioChannelLayoutTag_UseChannelDescriptions);
   EXPECT_EQ(output_layout->layout()->mNumberChannelDescriptions,
             static_cast<UInt32>(channels));
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[0].mChannelLabel,
-            kAudioChannelLabel_Left);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[0].mChannelFlags,
-            kAudioChannelFlags_AllOff);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[1].mChannelLabel,
-            kAudioChannelLabel_Right);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[1].mChannelFlags,
-            kAudioChannelFlags_AllOff);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[2].mChannelLabel,
-            kAudioChannelLabel_Center);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[2].mChannelFlags,
-            kAudioChannelFlags_AllOff);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[3].mChannelLabel,
-            kAudioChannelLabel_LFEScreen);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[3].mChannelFlags,
-            kAudioChannelFlags_AllOff);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[4].mChannelLabel,
-            kAudioChannelLabel_RearSurroundLeft);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[4].mChannelFlags,
-            kAudioChannelFlags_AllOff);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[5].mChannelLabel,
-            kAudioChannelLabel_RearSurroundRight);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[5].mChannelFlags,
-            kAudioChannelFlags_AllOff);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[6].mChannelLabel,
-            kAudioChannelLabel_LeftCenter);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[6].mChannelFlags,
-            kAudioChannelFlags_AllOff);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[7].mChannelLabel,
-            kAudioChannelLabel_RightCenter);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[7].mChannelFlags,
-            kAudioChannelFlags_AllOff);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[8].mChannelLabel,
-            kAudioChannelLabel_CenterSurround);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[8].mChannelFlags,
-            kAudioChannelFlags_AllOff);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[9].mChannelLabel,
-            kAudioChannelLabel_LeftSurround);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[9].mChannelFlags,
-            kAudioChannelFlags_AllOff);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[10].mChannelLabel,
-            kAudioChannelLabel_RightSurround);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[10].mChannelFlags,
-            kAudioChannelFlags_AllOff);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[11].mChannelLabel,
-            kAudioChannelLabel_Unknown);
-  EXPECT_EQ(output_layout->layout()->mChannelDescriptions[11].mChannelFlags,
-            kAudioChannelFlags_AllOff);
+  for (int i = 0; i < channels; i++) {
+    EXPECT_EQ(output_layout->layout()->mChannelDescriptions[i].mChannelLabel,
+              kAudioChannelLabel_Unknown);
+    EXPECT_EQ(output_layout->layout()->mChannelDescriptions[i].mChannelFlags,
+              kAudioChannelFlags_AllOff);
+  }
 }
 
 TEST(ChannelLayoutUtilMac, ChannelLayout7Point1ToAudioChannelLayout) {
diff --git a/media/capture/video/apple/sample_buffer_transformer.cc b/media/capture/video/apple/sample_buffer_transformer.cc
index 7e10c7f4..2c858708 100644
--- a/media/capture/video/apple/sample_buffer_transformer.cc
+++ b/media/capture/video/apple/sample_buffer_transformer.cc
@@ -601,8 +601,8 @@
 
   // The rotated_pixel_buffer might not be the same size as source_pixel_buffer
   // since source_pixel_buffer gets rotated by rotation_angle_.
-  if (pixel_buffer_rotator_->Rotate(source_pixel_buffer, rotated_pixel_buffer,
-                                    rotation_angle_)) {
+  if (pixel_buffer_rotator_->Rotate(
+          source_pixel_buffer, rotated_pixel_buffer.get(), rotation_angle_)) {
     return base::apple::ScopedCFTypeRef<CVPixelBufferRef>(rotated_pixel_buffer);
   } else {
     return base::apple::ScopedCFTypeRef<CVPixelBufferRef>();
diff --git a/media/capture/video/apple/sample_buffer_transformer_unittest.mm b/media/capture/video/apple/sample_buffer_transformer_unittest.mm
index 2563bd0..ec0d02b4 100644
--- a/media/capture/video/apple/sample_buffer_transformer_unittest.mm
+++ b/media/capture/video/apple/sample_buffer_transformer_unittest.mm
@@ -397,12 +397,12 @@
   base::apple::ScopedCFTypeRef<CVPixelBufferRef> output_pixel_buffer =
       transformer->Transform(input_sample_buffer.get());
   base::apple::ScopedCFTypeRef<CVPixelBufferRef> roatated_pixel_buffer =
-      transformer->Rotate(output_pixel_buffer);
-  EXPECT_TRUE(CVPixelBufferGetIOSurface(roatated_pixel_buffer));
+      transformer->Rotate(output_pixel_buffer.get());
+  EXPECT_TRUE(CVPixelBufferGetIOSurface(roatated_pixel_buffer.get()));
   EXPECT_EQ(kFullResolutionWidth,
-            CVPixelBufferGetHeight(roatated_pixel_buffer));
+            CVPixelBufferGetHeight(roatated_pixel_buffer.get()));
   EXPECT_EQ(kFullResolutionHeight,
-            CVPixelBufferGetWidth(roatated_pixel_buffer));
+            CVPixelBufferGetWidth(roatated_pixel_buffer.get()));
 }
 #endif
 
diff --git a/media/capture/video/apple/video_capture_device_avfoundation.mm b/media/capture/video/apple/video_capture_device_avfoundation.mm
index a5f758fd..1dcc54e 100644
--- a/media/capture/video/apple/video_capture_device_avfoundation.mm
+++ b/media/capture/video/apple/video_capture_device_avfoundation.mm
@@ -1054,9 +1054,9 @@
     // the original size, rotated_pixelBuffer need to scale it to its original
     // size by transforming it.
     base::apple::ScopedCFTypeRef<CVPixelBufferRef> rotated_pixelBuffer =
-        _sampleBufferTransformer->Rotate(pixelBuffer);
+        _sampleBufferTransformer->Rotate(pixelBuffer.get());
     base::apple::ScopedCFTypeRef<CVPixelBufferRef> final_pixel_buffer =
-        _sampleBufferTransformer->Transform(rotated_pixelBuffer);
+        _sampleBufferTransformer->Transform(rotated_pixelBuffer.get());
 
 #endif
 
diff --git a/media/capture/video/ios/pixel_buffer_rotator.cc b/media/capture/video/ios/pixel_buffer_rotator.cc
index 61d79c8..d46b27c 100644
--- a/media/capture/video/ios/pixel_buffer_rotator.cc
+++ b/media/capture/video/ios/pixel_buffer_rotator.cc
@@ -45,11 +45,11 @@
       default:
         NOTREACHED();
     }
-    OSStatus error = VTSessionSetProperty(rotation_session_,
+    OSStatus error = VTSessionSetProperty(rotation_session_.get(),
                                           kVTPixelRotationPropertyKey_Rotation,
                                           rotation_angle);
     CHECK(error == noErr) << "Unexpected RotationPropertyKey error: " << error;
-    error = VTPixelRotationSessionRotateImage(rotation_session_, source,
+    error = VTPixelRotationSessionRotateImage(rotation_session_.get(), source,
                                               destination);
     if (error == kVTPixelRotationNotSupportedErr) {
       return false;
@@ -63,7 +63,7 @@
 
 PixelBufferRotator::~PixelBufferRotator() {
   if (__builtin_available(iOS 16, *)) {
-    VTPixelRotationSessionInvalidate(rotation_session_);
+    VTPixelRotationSessionInvalidate(rotation_session_.get());
   }
 }
 
diff --git a/media/fuchsia/video/fuchsia_video_decoder.cc b/media/fuchsia/video/fuchsia_video_decoder.cc
index d935042b..da07689 100644
--- a/media/fuchsia/video/fuchsia_video_decoder.cc
+++ b/media/fuchsia/video/fuchsia_video_decoder.cc
@@ -121,6 +121,7 @@
                      gpu::SHARED_IMAGE_USAGE_SCANOUT |
                      gpu::SHARED_IMAGE_USAGE_VIDEO_DECODE;
 
+    scoped_refptr<gpu::ClientSharedImage> client_shared_image;
     if (IsMultiPlaneFormatForHardwareVideoEnabled()) {
       auto buffer_format = gmb->GetFormat();
 
@@ -137,20 +138,20 @@
       }
       shared_image_format.SetPrefersExternalSampler();
 
-      auto client_shared_image =
+      client_shared_image =
           raster_context_provider_->SharedImageInterface()->CreateSharedImage(
               shared_image_format, gmb->GetSize(), color_space,
               kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, usage,
               "FuchsiaVideoDecoder", gmb->CloneHandle());
-      CHECK(client_shared_image);
-      mailbox_ = client_shared_image->mailbox();
     } else {
-      mailbox_ =
+      client_shared_image =
           raster_context_provider_->SharedImageInterface()->CreateSharedImage(
               gmb.get(), nullptr, gfx::BufferPlane::DEFAULT, color_space,
               kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, usage,
               "FuchsiaVideoDecoder");
     }
+    CHECK(client_shared_image);
+    mailbox_ = client_shared_image->mailbox();
 
     create_sync_token_ = raster_context_provider_->SharedImageInterface()
                              ->GenVerifiedSyncToken();
diff --git a/media/fuchsia/video/fuchsia_video_decoder_unittest.cc b/media/fuchsia/video/fuchsia_video_decoder_unittest.cc
index 40249e1..c7d9dbe 100644
--- a/media/fuchsia/video/fuchsia_video_decoder_unittest.cc
+++ b/media/fuchsia/video/fuchsia_video_decoder_unittest.cc
@@ -144,7 +144,7 @@
     return base::MakeRefCounted<gpu::ClientSharedImage>(result);
   }
 
-  gpu::Mailbox CreateSharedImage(
+  scoped_refptr<gpu::ClientSharedImage> CreateSharedImage(
       gfx::GpuMemoryBuffer* gpu_memory_buffer,
       gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
       gfx::BufferPlane plane,
@@ -155,7 +155,7 @@
       base::StringPiece debug_label) override {
     auto result = GenerateMailboxForGMBHandle(gpu_memory_buffer->CloneHandle());
     mailboxes_.insert(result);
-    return result;
+    return base::MakeRefCounted<gpu::ClientSharedImage>(result);
   }
 
   void UpdateSharedImage(const gpu::SyncToken& sync_token,
diff --git a/media/gpu/v4l2/stateless/vp9_delegate.cc b/media/gpu/v4l2/stateless/vp9_delegate.cc
index 9e512d05..1ef2e4d 100644
--- a/media/gpu/v4l2/stateless/vp9_delegate.cc
+++ b/media/gpu/v4l2/stateless/vp9_delegate.cc
@@ -14,19 +14,20 @@
 
 namespace media {
 
-class V4L2VP9Picture : public VP9Picture {
+class StatelessVP9Picture : public VP9Picture {
  public:
-  explicit V4L2VP9Picture(scoped_refptr<StatelessDecodeSurface> dec_surface)
+  explicit StatelessVP9Picture(
+      scoped_refptr<StatelessDecodeSurface> dec_surface)
       : dec_surface_(std::move(dec_surface)) {}
 
-  V4L2VP9Picture(const V4L2VP9Picture&) = delete;
-  V4L2VP9Picture& operator=(const V4L2VP9Picture&) = delete;
+  StatelessVP9Picture(const StatelessVP9Picture&) = delete;
+  StatelessVP9Picture& operator=(const StatelessVP9Picture&) = delete;
 
  private:
-  ~V4L2VP9Picture() override = default;
+  ~StatelessVP9Picture() override = default;
 
   scoped_refptr<VP9Picture> CreateDuplicate() override {
-    return base::MakeRefCounted<V4L2VP9Picture>(dec_surface_);
+    return base::MakeRefCounted<StatelessVP9Picture>(dec_surface_);
   }
 
   scoped_refptr<StatelessDecodeSurface> dec_surface_;
@@ -145,7 +146,7 @@
     return nullptr;
   }
 
-  return base::MakeRefCounted<V4L2VP9Picture>(std::move(dec_surface));
+  return base::MakeRefCounted<StatelessVP9Picture>(std::move(dec_surface));
 }
 
 DecodeStatus VP9Delegate::SubmitDecode(
diff --git a/media/gpu/v4l2/v4l2_stateful_video_decoder.cc b/media/gpu/v4l2/v4l2_stateful_video_decoder.cc
index f52b7e89..7e004ee 100644
--- a/media/gpu/v4l2/v4l2_stateful_video_decoder.cc
+++ b/media/gpu/v4l2/v4l2_stateful_video_decoder.cc
@@ -180,9 +180,9 @@
 namespace media {
 
 // Stateful drivers need to be passed whole frames (see IsNewH264Frame() above).
-// Some implementations(Hana MTK8173, but not Trogdor SC7180), don't support
+// Some implementations (Hana MTK8173, but not Trogdor SC7180), don't support
 // multiple whole frames enqueued in a single OUTPUT queue buffer. This class
-// helps processing and gathering DecoderBuffers into full frames.
+// helps processing, slicing and gathering DecoderBuffers into full frames.
 class H264FrameReassembler {
  public:
   H264FrameReassembler() = default;
@@ -203,28 +203,31 @@
           VideoDecoder::DecodeCB decode_cb);
 
   // Used for End-of-Stream situations when a caller needs to reassemble
-  // explcitily (an EOS marks a frame boundary, we can't parse it).
+  // explicitly (an EOS marks a frame boundary, we can't parse it).
   scoped_refptr<DecoderBuffer> AssembleAndFlushFragments() {
     return ReassembleFragments(frame_fragments_);
   }
   bool HasFragments() const { return !frame_fragments_.empty(); }
 
  private:
+  // Data structure returned by FindH264FrameBoundary().
+  struct FrameBoundaryInfo {
+    // True if the NALU immediately before the boundary is a whole frame, e.g.
+    // an SPS, PPS, EOSeq or SEIMessage.
+    bool is_whole_frame;
+    // True if the NALU marks the beginning of a new frame (but itself isn't
+    // necessarily a whole frame, for that see |is_whole_frame|). This implies
+    // that any previously buffered fragments/slices can be reassembled into a
+    // whole frame.
+    bool is_start_of_new_frame;
+    // Size in bytes of the NALU under analysis.
+    off_t nalu_size;
+  };
   // Parses |data| and returns either absl::nullopt, if parsing |data| fails, or
-  // a pair of a boolean flag and a size_t, where:
-  // - The boolean flag tells whether |data| contains the beginning of a new
-  //   frame (and necessarily the end of a previous one, if any).
-  // - If said flag is true, then the returned size_t is the length of the first
-  //   found whole frame.
-  // - If said flag is false, then the returned size_t is the size of the first
-  //   fragment (a.k.a. "slice"), which might be smaller than |size|.
+  // a FrameBoundaryInfo describing the first |nalu_size| bytes of |data|.
   //
-  // It is assumed that:
-  // - |data| contains an integer number of NALUs.
-  // - |data| contains at most 2 whole frames.
-  //   TODO(mcasas): Support more frames, as seen in e.g. CAPCM*1_Sand_E.h264,
-  //   switch_1080p_720p_240frames.h264.
-  absl::optional<std::pair<bool, size_t>> FindH264FrameBoundary(
+  // It is assumed that |data| contains an integer number of NALUs.
+  absl::optional<struct FrameBoundaryInfo> FindH264FrameBoundary(
       const uint8_t* const data,
       size_t size);
 
@@ -412,9 +415,15 @@
   }
   DCHECK_EQ(v4l2_format->fmt.pix_mp.pixelformat, profile_as_v4l2_fourcc);
 
-  constexpr size_t kNumInputBuffers = 8;
-  if (OUTPUT_queue_->AllocateBuffers(kNumInputBuffers, V4L2_MEMORY_MMAP,
-                                     /*incoherent=*/false) < kNumInputBuffers) {
+  const bool is_h264 =
+      VideoCodecProfileToVideoCodec(config.profile()) == VideoCodec::kH264;
+  constexpr size_t kNumInputBuffersH264 = 16;
+  constexpr size_t kNumInputBuffersVPx = 8;
+  const auto num_input_buffers =
+      is_h264 ? kNumInputBuffersH264 : kNumInputBuffersVPx;
+  if (OUTPUT_queue_->AllocateBuffers(num_input_buffers, V4L2_MEMORY_MMAP,
+                                     /*incoherent=*/false) <
+      num_input_buffers) {
     std::move(init_cb).Run(DecoderStatus::Codes::kFailedToCreateDecoder);
     return;
   }
@@ -436,7 +445,7 @@
   aspect_ratio_ = config.aspect_ratio();
   output_cb_ = std::move(output_cb);
   profile_ = config.profile();
-  if (VideoCodecProfileToVideoCodec(profile_) == VideoCodec::kH264) {
+  if (is_h264) {
     h264_frame_reassembler_ = std::make_unique<H264FrameReassembler>();
   }
 
@@ -1116,69 +1125,65 @@
 std::vector<std::pair<scoped_refptr<DecoderBuffer>, VideoDecoder::DecodeCB>>
 H264FrameReassembler::Process(scoped_refptr<DecoderBuffer> buffer,
                               VideoDecoder::DecodeCB decode_cb) {
-  const auto result =
-      FindH264FrameBoundary(buffer->data(), buffer->data_size());
-  if (!result.has_value()) {
-    LOG(ERROR) << "Failed parsing H.264 DecoderBuffer";
-    std::move(decode_cb).Run(DecoderStatus::Codes::kFailed);
-    return {};
-  }
-
-  // If |buffer| has part of a frame (i.e. FindH264FrameBoundary() didn't find a
-  // frame boundary / the beginning of a new frame), we can't do much: store it
-  // for later reassembly. Otherwise, |buffer| marks the beginning of a new
-  // frame and needs further processing.
-  const bool is_new_frame_found = result->first;
-  if (!is_new_frame_found) {
-    VLOGF(3) << "|buffer| is a frame fragment, storing it for reassembly.";
-    frame_fragments_.emplace_back(std::move(buffer));
-    std::move(decode_cb).Run(DecoderStatus::Codes::kOk);
-    return {};
-  }
-
   std::vector<std::pair<scoped_refptr<DecoderBuffer>, VideoDecoder::DecodeCB>>
       whole_frames;
 
-  // If we reach here, |buffer| marks a new frame; reassemble any previously
-  // stored |frame_fragments_| (a.k.a. "slices") into a new DecoderBuffer.
-  if (HasFragments()) {
-    VLOGF(3) << "|buffer| is a new frame fragment; " << frame_fragments_.size()
-             << " currently stored frame fragment(s) can be reassembled.";
-    whole_frames.emplace_back(std::make_pair(
-        ReassembleFragments(frame_fragments_), base::DoNothing()));
-  }
+  auto* buffer_pointer = buffer->data();
+  auto remaining_buffer_size = buffer->data_size();
 
-  const size_t found_frame_size = result->second;
-  const bool contains_multiple_frames = found_frame_size < buffer->data_size();
-  if (!contains_multiple_frames) {
-    // We cannot know if |buffer| is a full frame or a fragment (we'll only know
-    // when we find the beginning of the next frame). Save the current |buffer|
-    // as the first fragment for the next time we call this method.
-    frame_fragments_.emplace_back(std::move(buffer));
+  do {
+    const auto nalu_info =
+        FindH264FrameBoundary(buffer_pointer, remaining_buffer_size);
+    if (!nalu_info.has_value()) {
+      LOG(ERROR) << "Failed parsing H.264 DecoderBuffer";
+      std::move(decode_cb).Run(DecoderStatus::Codes::kFailed);
+      return {};
+    }
+    const size_t found_nalu_size =
+        base::checked_cast<size_t>(nalu_info->nalu_size);
+
+    if (nalu_info->is_start_of_new_frame && HasFragments()) {
+      VLOGF(3) << frame_fragments_.size()
+               << " currently stored frame fragment(s) can be reassembled.";
+      whole_frames.emplace_back(std::make_pair(
+          ReassembleFragments(frame_fragments_), base::DoNothing()));
+    }
+
+    if (nalu_info->is_whole_frame) {
+      VLOGF(3) << "Found a whole frame, size=" << found_nalu_size << " bytes";
+      whole_frames.emplace_back(std::make_pair(
+          DecoderBuffer::CopyFrom(buffer_pointer, found_nalu_size),
+          base::DoNothing()));
+
+      buffer_pointer += found_nalu_size;
+      remaining_buffer_size -= found_nalu_size;
+      continue;
+    }
+
+    VLOGF(3) << "This was a frame fragment; storing it for later reassembly.";
+    frame_fragments_.emplace_back(
+        DecoderBuffer::CopyFrom(buffer_pointer, found_nalu_size));
+
+    buffer_pointer += found_nalu_size;
+    remaining_buffer_size -= found_nalu_size;
+  } while (remaining_buffer_size);
+
+  // |decode_cb| is used to signal to our client that encoded chunks have been
+  // "accepted", and that we are ready to receive more. If we have found (some)
+  // whole frame(s), then we can just return |decode_cb| so that it can be Run()
+  // at the actual enqueueing in driver moment; but if there were no frames
+  // found, we need to signal the callback now otherwise the client might stop
+  // sending fragments altogether and we'll wait forever.
+  if (whole_frames.empty()) {
     std::move(decode_cb).Run(DecoderStatus::Codes::kOk);
-    return whole_frames;
+  } else {
+    whole_frames.back().second = std::move(decode_cb);
   }
 
-  // The code here assumes there's just two whole frames in |buffer|.
-  // TODO(mcasas): Support more, as seen in e.g. CAPCM*1_Sand_E.h264.
-  VLOGF(3) << "|buffer| contains several frames, need to split them.";
-  auto first_frame = DecoderBuffer::CopyFrom(buffer->data(), found_frame_size);
-
-  const auto h264_second_frame_size = buffer->data_size() - found_frame_size;
-  auto second_frame = DecoderBuffer::CopyFrom(buffer->data() + found_frame_size,
-                                              h264_second_frame_size);
-
-  // Note that |decode_cb| is a OnceCallback, so should be called only once,
-  // when the |second_frame| is enqueued.
-  whole_frames.emplace_back(
-      std::make_pair(std::move(first_frame), base::DoNothing()));
-  whole_frames.emplace_back(
-      std::make_pair(std::move(second_frame), std::move(decode_cb)));
-
   return whole_frames;
 }
 
-absl::optional<std::pair<bool, size_t>>
+absl::optional<struct H264FrameReassembler::FrameBoundaryInfo>
 H264FrameReassembler::FindH264FrameBoundary(const uint8_t* const data,
                                             size_t data_size) {
   h264_parser_.SetStream(data, data_size);
@@ -1213,7 +1218,7 @@
     const auto nalu_size = nalu.data - data + nalu.size;
     VLOGF(4) << "H264NALU type " << kKnownNALUNames[nalu.nal_unit_type]
              << ", NALU size=" << nalu_size
-             << "bytes, payload size=" << nalu.size << " bytes";
+             << " bytes, payload size=" << nalu.size << " bytes";
 
     switch (nalu.nal_unit_type) {
       case H264NALU::kSPS:
@@ -1222,14 +1227,20 @@
           LOG(ERROR) << "Could not parse SPS header.";
           return absl::nullopt;
         }
-        return std::make_pair(true, nalu_size);
+        previous_slice_header_.reset();
+        return FrameBoundaryInfo{.is_whole_frame = true,
+                                 .is_start_of_new_frame = true,
+                                 .nalu_size = nalu_size};
       case H264NALU::kPPS:
         result = h264_parser_.ParsePPS(&pps_id_);
         if (result != H264Parser::kOk) {
           LOG(ERROR) << "Could not parse PPS header.";
           return absl::nullopt;
         }
-        return std::make_pair(true, nalu_size);
+        previous_slice_header_.reset();
+        return FrameBoundaryInfo{.is_whole_frame = true,
+                                 .is_start_of_new_frame = true,
+                                 .nalu_size = nalu_size};
       case H264NALU::kNonIDRSlice:
       case H264NALU::kIDRSlice: {
         H264SliceHeader curr_slice_header;
@@ -1238,17 +1249,20 @@
           // In this function we just want to find frame boundaries, so return
           // but don't mark an error.
           LOG(WARNING) << "Could not parse NALU header.";
-          return std::make_pair(true, nalu_size);
+          return FrameBoundaryInfo{.is_whole_frame = true,
+                                   .is_start_of_new_frame = false,
+                                   .nalu_size = nalu_size};
         }
         const bool is_new_frame =
-            !previous_slice_header_ ||
-            (previous_slice_header_ &&
-             IsNewH264Frame(h264_parser_.GetSPS(sps_id_),
-                            h264_parser_.GetPPS(pps_id_),
-                            previous_slice_header_.get(), &curr_slice_header));
+            previous_slice_header_ &&
+            IsNewH264Frame(h264_parser_.GetSPS(sps_id_),
+                           h264_parser_.GetPPS(pps_id_),
+                           previous_slice_header_.get(), &curr_slice_header);
         previous_slice_header_ =
             std::make_unique<H264SliceHeader>(curr_slice_header);
-        return std::make_pair(is_new_frame, nalu_size);
+        return FrameBoundaryInfo{.is_whole_frame = false,
+                                 .is_start_of_new_frame = is_new_frame,
+                                 .nalu_size = nalu_size};
       }
       case H264NALU::kSEIMessage:
       case H264NALU::kAUD:
@@ -1262,7 +1276,10 @@
       case H264NALU::kReserved17:
       case H264NALU::kReserved18:
         // Anything else than SPS, PPS and Non/IDRs marks a new frame boundary.
-        return std::make_pair(true, nalu_size);
+        previous_slice_header_.reset();
+        return FrameBoundaryInfo{.is_whole_frame = true,
+                                 .is_start_of_new_frame = true,
+                                 .nalu_size = nalu_size};
       default:
         NOTREACHED_NORETURN() << "Unknown NALU, id: " << nalu.nal_unit_type;
     }
diff --git a/media/media_options.gni b/media/media_options.gni
index 669e9d4c..2deb6fc 100644
--- a/media/media_options.gni
+++ b/media/media_options.gni
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/chromeos/args.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
diff --git a/media/mojo/BUILD.gn b/media/mojo/BUILD.gn
index c6d3e61..220691da 100644
--- a/media/mojo/BUILD.gn
+++ b/media/mojo/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//media/media_options.gni")
 import("//testing/test.gni")
 
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn
index 90701484..778b1b9b 100644
--- a/media/mojo/services/BUILD.gn
+++ b/media/mojo/services/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//media/gpu/args.gni")
 import("//media/media_options.gni")
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc
index 0c57889e..ad3cd2a3 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -1269,24 +1269,25 @@
 #endif
 
       constexpr char kDebugLabel[] = "MediaGmbVideoFramePool";
+      scoped_refptr<gpu::ClientSharedImage> client_shared_image;
       if (base::FeatureList::IsEnabled(kUseMultiPlaneFormatForSoftwareVideo)) {
         viz::SharedImageFormat si_format =
             OutputFormatToSharedImageFormat(output_format_, plane);
         if (SetPrefersExternalSampler(si_format)) {
           plane_resource.is_multiplanar_buffer = true;
         }
-        auto client_shared_image = sii->CreateSharedImage(
+        client_shared_image = sii->CreateSharedImage(
             si_format, gpu_memory_buffer->GetSize(), color_space,
             kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, usage, kDebugLabel,
             gpu_memory_buffer->CloneHandle());
-        CHECK(client_shared_image);
-        plane_resource.mailbox = client_shared_image->mailbox();
       } else {
-        plane_resource.mailbox = sii->CreateSharedImage(
+        client_shared_image = sii->CreateSharedImage(
             gpu_memory_buffer, gpu_factories_->GpuMemoryBufferManager(),
             GetSharedImageBufferPlane(output_format_, plane), color_space,
             kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, usage, kDebugLabel);
       }
+      CHECK(client_shared_image);
+      plane_resource.mailbox = client_shared_image->mailbox();
     } else if (!plane_resource.mailbox.IsZero()) {
       sii->UpdateSharedImage(frame_resources->sync_token,
                              plane_resource.mailbox);
diff --git a/mojo/public/mojom/base/BUILD.gn b/mojo/public/mojom/base/BUILD.gn
index 74725386..b1920c1 100644
--- a/mojo/public/mojom/base/BUILD.gn
+++ b/mojo/public/mojom/base/BUILD.gn
@@ -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("//build/config/chromeos/ui_mode.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom_component("base") {
@@ -56,8 +57,12 @@
   webui_module_path = "chrome://resources/mojo/mojo/public/mojom/base"
 
   # Still widely used by Closure Compiler targets on ChromeOS, so generate
-  # WebUI bindings in JavaScript.
-  use_typescript_sources = false
+  # WebUI bindings in JavaScript for that platform.
+  use_typescript_sources = !is_chromeos_ash
+
+  # Always generate legacy bindings since this target is used by Blink, fuzzers,
+  # etc and not just by WebUI.
+  generate_legacy_js_bindings = true
 
   output_prefix = "mojo_base_mojom"
   macro_prefix = "MOJO_BASE_MOJOM"
diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni
index f361f15..60419c5 100644
--- a/mojo/public/tools/bindings/mojom.gni
+++ b/mojo/public/tools/bindings/mojom.gni
@@ -8,13 +8,14 @@
 import("//ui/webui/resources/tools/generate_grd.gni")
 import("//ui/webui/webui_features.gni")
 
+import("//build/config/cast.gni")
+
 # TODO(rockot): Maybe we can factor these dependencies out of //mojo. They're
 # used to conditionally enable message ID scrambling in a way which is
 # consistent across toolchains and which is affected by branded vs non-branded
 # Chrome builds. Ideally we could create some generic knobs here that could be
 # flipped elsewhere though.
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
 import("//build/config/nacl/config.gni")
@@ -1933,11 +1934,10 @@
     not_needed(invoker, [ "use_typescript_sources" ])
   }
 
-  # Don't allow new JavaScript WebUI bindings on non-ChromeOS platforms.
+  # Don't allow JavaScript WebUI bindings on non-ChromeOS platforms.
   if (!use_typescript_for_target && defined(invoker.webui_module_path)) {
     assert(
-        is_chromeos_ash || invoker.webui_module_path ==
-                               "chrome://resources/mojo/mojo/public/mojom/base",
+        is_chromeos_ash,
         "WebUI bindings should be in TypeScript on non-ChromeOS platforms. " +
             "Remove use_typescript_sources = false")
   }
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 129c28f..324808e0 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/compiler/compiler.gni")
 import("//build/config/cronet/config.gni")
diff --git a/net/extras/sqlite/cookie_crypto_delegate.h b/net/extras/sqlite/cookie_crypto_delegate.h
index 2e9fc8ed..cae5703 100644
--- a/net/extras/sqlite/cookie_crypto_delegate.h
+++ b/net/extras/sqlite/cookie_crypto_delegate.h
@@ -5,6 +5,8 @@
 #ifndef NET_EXTRAS_SQLITE_COOKIE_CRYPTO_DELEGATE_H_
 #define NET_EXTRAS_SQLITE_COOKIE_CRYPTO_DELEGATE_H_
 
+#include <string>
+
 #include "base/component_export.h"
 
 namespace net {
@@ -14,13 +16,13 @@
  public:
   virtual ~CookieCryptoDelegate() = default;
 
-  // Encrypt |plaintext| string and store the result in |ciphertext|.  This
-  // method is always functional even if ShouldEncrypt() is false.
+  // Encrypt `plaintext` string and store the result in `ciphertext`. Returns
+  // true if the encryption succeeded.
   virtual bool EncryptString(const std::string& plaintext,
                              std::string* ciphertext) = 0;
 
-  // Decrypt |ciphertext| string and store the result in |plaintext|.  This
-  // method is always functional even if ShouldEncrypt() is false.
+  // Decrypt `ciphertext` string and store the result in `plaintext`. Returns
+  // true if the decryption succeeded.
   virtual bool DecryptString(const std::string& ciphertext,
                              std::string* plaintext) = 0;
 };
diff --git a/pdf/features.gni b/pdf/features.gni
index 7a5288d..a544e4c 100644
--- a/pdf/features.gni
+++ b/pdf/features.gni
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//ash/webui/media_app_ui/media_app_ui.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 
 # Most build code won't need to include this file. Instead you can
 # unconditionally depend on "//pdf" which will be a no-op when PDF support is
diff --git a/ppapi/buildflags/buildflags.gni b/ppapi/buildflags/buildflags.gni
index 9f1cc34..10ce8caa 100644
--- a/ppapi/buildflags/buildflags.gni
+++ b/ppapi/buildflags/buildflags.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 
 declare_args() {
   # Enables basic plugin support. This enables support for registering and
diff --git a/printing/buildflags/buildflags.gni b/printing/buildflags/buildflags.gni
index fa9004e2..b9f3b40 100644
--- a/printing/buildflags/buildflags.gni
+++ b/printing/buildflags/buildflags.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/args.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/features.gni")
diff --git a/printing/emf_win_unittest.cc b/printing/emf_win_unittest.cc
index e02dc28..b2fe6777 100644
--- a/printing/emf_win_unittest.cc
+++ b/printing/emf_win_unittest.cc
@@ -90,7 +90,8 @@
   settings->set_device_name(u"UnitTest Printer");
 
   // Initialize it.
-  PrintingContextWin context(this);
+  PrintingContextWin context(this,
+                             PrintingContext::ProcessBehavior::kOopDisabled);
   EXPECT_EQ(mojom::ResultCode::kSuccess,
             context.InitWithSettingsForTest(std::move(settings)));
 
diff --git a/printing/printing_context.cc b/printing/printing_context.cc
index 6aae8700..94f51e9f 100644
--- a/printing/printing_context.cc
+++ b/printing/printing_context.cc
@@ -29,11 +29,13 @@
 
 }  // namespace
 
-PrintingContext::PrintingContext(Delegate* delegate)
+PrintingContext::PrintingContext(Delegate* delegate,
+                                 ProcessBehavior process_behavior)
     : settings_(std::make_unique<PrintSettings>()),
       delegate_(delegate),
       in_print_job_(false),
-      abort_printing_(false) {
+      abort_printing_(false),
+      process_behavior_(process_behavior) {
   DCHECK(delegate_);
 }
 
@@ -42,11 +44,11 @@
 // static
 std::unique_ptr<PrintingContext> PrintingContext::Create(
     Delegate* delegate,
-    bool skip_system_calls) {
+    ProcessBehavior process_behavior) {
   return g_printing_context_factory_for_test
              ? g_printing_context_factory_for_test->CreatePrintingContext(
-                   delegate, skip_system_calls)
-             : PrintingContext::CreateImpl(delegate, skip_system_calls);
+                   delegate, process_behavior)
+             : PrintingContext::CreateImpl(delegate, process_behavior);
 }
 
 // static
diff --git a/printing/printing_context.h b/printing/printing_context.h
index c753f04..6db58a99 100644
--- a/printing/printing_context.h
+++ b/printing/printing_context.h
@@ -64,6 +64,28 @@
 #endif
   };
 
+  enum class ProcessBehavior {
+    // Out-of-process support is disabled.  All platform printing calls are
+    // performed in the browser process.
+    kOopDisabled,
+#if BUILDFLAG(ENABLE_OOP_PRINTING)
+    // Out-of-process support is enabled.  This is for `PrintingContext`
+    // objects which exist in the PrintBackend service.  These objects make
+    // platform printing calls.
+    kOopEnabledPerformSystemCalls,
+    // Out-of-process support is enabled.  This is for `PrintingContext`
+    // objects which exist in the browser process.  These objects normally skip
+    // doing platform printing calls, deferring to an associated
+    // `PrintingContext` that is running in a PrintBackend service (i.e.,
+    // deferring to a `PrintingContext` with `kOopEnabledPerformSystemCalls`).
+    // An exception to deferring platform calls in this case is for platforms
+    // that cannot display a system print dialog from a PrintBackend service.
+    // On such platforms the relevant calls to invoke a system print dialog
+    // are still made from the browser process.
+    kOopEnabledSkipSystemCalls,
+#endif
+  };
+
   PrintingContext(const PrintingContext&) = delete;
   PrintingContext& operator=(const PrintingContext&) = delete;
   virtual ~PrintingContext();
@@ -157,14 +179,20 @@
 #endif
 
   // Creates an instance of this object.
-  static std::unique_ptr<PrintingContext> Create(Delegate* delegate,
-                                                 bool skip_system_calls);
+  static std::unique_ptr<PrintingContext> Create(
+      Delegate* delegate,
+      ProcessBehavior process_behavior);
 
   // Test method for generating printing contexts for testing.  This overrides
   // the platform-specific implementations of CreateImpl().
   static void SetPrintingContextFactoryForTest(
       PrintingContextFactoryForTest* factory);
 
+  // Determine process behavior, which can determine if system calls should be
+  // made and if certain extra code paths should be followed to support
+  // out-of-process printing.
+  ProcessBehavior process_behavior() const { return process_behavior_; }
+
   void set_margin_type(mojom::MarginType type);
   void set_is_modifiable(bool is_modifiable);
 
@@ -177,31 +205,17 @@
   int job_id() const { return job_id_; }
 
  protected:
-  explicit PrintingContext(Delegate* delegate);
+  PrintingContext(Delegate* delegate, ProcessBehavior process_behavior);
 
   // Creates an instance of this object. Implementers of this interface should
   // implement this method to create an object of their implementation.
-  static std::unique_ptr<PrintingContext> CreateImpl(Delegate* delegate,
-                                                     bool skip_system_calls);
+  static std::unique_ptr<PrintingContext> CreateImpl(
+      Delegate* delegate,
+      ProcessBehavior process_behavior);
 
   // Reinitializes the settings for object reuse.
   void ResetSettings();
 
-  // Determine if system calls should be skipped by this instance.
-  bool skip_system_calls() const {
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-    return skip_system_calls_;
-#else
-    return false;
-#endif
-  }
-
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-  // Make the one-way adjustment to have all system calls skipped by this
-  // `PrintingContext` instance.
-  void set_skip_system_calls() { skip_system_calls_ = true; }
-#endif
-
   // Does bookkeeping when an error occurs.
   virtual mojom::ResultCode OnError();
 
@@ -221,11 +235,7 @@
   int job_id_;
 
  private:
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-  // If this instance of PrintingContext should skip making any system calls
-  // to the operating system.
-  bool skip_system_calls_ = false;
-#endif
+  const ProcessBehavior process_behavior_;
 };
 
 }  // namespace printing
diff --git a/printing/printing_context_android.cc b/printing/printing_context_android.cc
index 80a40fc3..e1756eb 100644
--- a/printing/printing_context_android.cc
+++ b/printing/printing_context_android.cc
@@ -13,6 +13,7 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
+#include "base/check_op.h"
 #include "base/files/file.h"
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
@@ -63,8 +64,8 @@
 // static
 std::unique_ptr<PrintingContext> PrintingContext::CreateImpl(
     Delegate* delegate,
-    bool skip_system_calls) {
-  DCHECK(!skip_system_calls);
+    ProcessBehavior process_behavior) {
+  DCHECK_EQ(process_behavior, ProcessBehavior::kOopDisabled);
   return std::make_unique<PrintingContextAndroid>(delegate);
 }
 
@@ -86,7 +87,7 @@
 }
 
 PrintingContextAndroid::PrintingContextAndroid(Delegate* delegate)
-    : PrintingContext(delegate) {
+    : PrintingContext(delegate, ProcessBehavior::kOopDisabled) {
   // The constructor is run in the IO thread.
 }
 
diff --git a/printing/printing_context_chromeos.cc b/printing/printing_context_chromeos.cc
index f3ff67f..11c2d149 100644
--- a/printing/printing_context_chromeos.cc
+++ b/printing/printing_context_chromeos.cc
@@ -280,34 +280,33 @@
 // static
 std::unique_ptr<PrintingContext> PrintingContext::CreateImpl(
     Delegate* delegate,
-    bool skip_system_calls) {
-  auto context = std::make_unique<PrintingContextChromeos>(delegate);
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-  if (skip_system_calls)
-    context->set_skip_system_calls();
-#endif
-  return context;
+    ProcessBehavior process_behavior) {
+  return std::make_unique<PrintingContextChromeos>(delegate, process_behavior);
 }
 
 // static
 std::unique_ptr<PrintingContextChromeos>
 PrintingContextChromeos::CreateForTesting(
     Delegate* delegate,
+    ProcessBehavior process_behavior,
     std::unique_ptr<CupsConnection> connection) {
   // Private ctor.
-  return base::WrapUnique(
-      new PrintingContextChromeos(delegate, std::move(connection)));
+  return base::WrapUnique(new PrintingContextChromeos(
+      delegate, process_behavior, std::move(connection)));
 }
 
-PrintingContextChromeos::PrintingContextChromeos(Delegate* delegate)
-    : PrintingContext(delegate),
+PrintingContextChromeos::PrintingContextChromeos(
+    Delegate* delegate,
+    ProcessBehavior process_behavior)
+    : PrintingContext(delegate, process_behavior),
       connection_(CupsConnection::Create()),
       ipp_options_(WrapIpp(nullptr)) {}
 
 PrintingContextChromeos::PrintingContextChromeos(
     Delegate* delegate,
+    ProcessBehavior process_behavior,
     std::unique_ptr<CupsConnection> connection)
-    : PrintingContext(delegate),
+    : PrintingContext(delegate, process_behavior),
       connection_(std::move(connection)),
       ipp_options_(WrapIpp(nullptr)) {}
 
@@ -447,8 +446,11 @@
   DCHECK(!in_print_job_);
   in_print_job_ = true;
 
-  if (skip_system_calls())
+#if BUILDFLAG(ENABLE_OOP_PRINTING)
+  if (process_behavior() == ProcessBehavior::kOopEnabledSkipSystemCalls) {
     return mojom::ResultCode::kSuccess;
+  }
+#endif
 
   std::string converted_name;
   if (send_user_info_) {
diff --git a/printing/printing_context_chromeos.h b/printing/printing_context_chromeos.h
index 67bc0026..deb0bb3 100644
--- a/printing/printing_context_chromeos.h
+++ b/printing/printing_context_chromeos.h
@@ -22,9 +22,10 @@
  public:
   static std::unique_ptr<PrintingContextChromeos> CreateForTesting(
       Delegate* delegate,
+      ProcessBehavior process_behavior,
       std::unique_ptr<CupsConnection> connection);
 
-  explicit PrintingContextChromeos(Delegate* delegate);
+  PrintingContextChromeos(Delegate* delegate, ProcessBehavior process_behavior);
   PrintingContextChromeos(const PrintingContextChromeos&) = delete;
   PrintingContextChromeos& operator=(const PrintingContextChromeos&) = delete;
   ~PrintingContextChromeos() override;
@@ -52,6 +53,7 @@
  private:
   // For testing. Use CreateForTesting() to create.
   PrintingContextChromeos(Delegate* delegate,
+                          ProcessBehavior process_behavior,
                           std::unique_ptr<CupsConnection> connection);
 
   // Lazily initializes `printer_`.
diff --git a/printing/printing_context_chromeos_unittest.cc b/printing/printing_context_chromeos_unittest.cc
index 8992f6e..2b74ba7 100644
--- a/printing/printing_context_chromeos_unittest.cc
+++ b/printing/printing_context_chromeos_unittest.cc
@@ -72,7 +72,8 @@
     EXPECT_CALL(*connection, GetPrinter(kPrinterName))
         .WillOnce(Return(ByMove(std::move(unique_printer))));
     printing_context_ = PrintingContextChromeos::CreateForTesting(
-        this, std::move(unique_connection));
+        this, PrintingContext::ProcessBehavior::kOopDisabled,
+        std::move(unique_connection));
     auto settings = std::make_unique<PrintSettings>();
     settings->set_device_name(kPrinterName16);
     settings->set_send_user_info(send_user_info);
diff --git a/printing/printing_context_factory_for_test.h b/printing/printing_context_factory_for_test.h
index 6ef1b51..8498a18 100644
--- a/printing/printing_context_factory_for_test.h
+++ b/printing/printing_context_factory_for_test.h
@@ -15,7 +15,7 @@
  public:
   virtual std::unique_ptr<PrintingContext> CreatePrintingContext(
       PrintingContext::Delegate* delegate,
-      bool skip_system_calls) = 0;
+      PrintingContext::ProcessBehavior process_behavior) = 0;
 };
 
 }  // namespace printing
diff --git a/printing/printing_context_linux.cc b/printing/printing_context_linux.cc
index 2bb8fbf..49f0ddab 100644
--- a/printing/printing_context_linux.cc
+++ b/printing/printing_context_linux.cc
@@ -32,17 +32,13 @@
 // static
 std::unique_ptr<PrintingContext> PrintingContext::CreateImpl(
     Delegate* delegate,
-    bool skip_system_calls) {
-  auto context = std::make_unique<PrintingContextLinux>(delegate);
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-  if (skip_system_calls)
-    context->set_skip_system_calls();
-#endif
-  return context;
+    ProcessBehavior process_behavior) {
+  return std::make_unique<PrintingContextLinux>(delegate, process_behavior);
 }
 
-PrintingContextLinux::PrintingContextLinux(Delegate* delegate)
-    : PrintingContext(delegate), print_dialog_(nullptr) {}
+PrintingContextLinux::PrintingContextLinux(Delegate* delegate,
+                                           ProcessBehavior process_behavior)
+    : PrintingContext(delegate, process_behavior), print_dialog_(nullptr) {}
 
 PrintingContextLinux::~PrintingContextLinux() {
   ReleaseContext();
@@ -134,12 +130,15 @@
   document_name_ = document_name;
 
 #if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
-  if (skip_system_calls()) {
+  if (process_behavior() == ProcessBehavior::kOopEnabledSkipSystemCalls) {
     return mojom::ResultCode::kSuccess;
   }
 
-  if (features::ShouldPrintJobOop() &&
+  if (process_behavior() == ProcessBehavior::kOopEnabledPerformSystemCalls &&
       !settings_->system_print_dialog_data().empty()) {
+    // Take the settings captured by the browser process from the system print
+    // dialog and apply them to this printing context in the PrintBackend
+    // service.
     if (!print_dialog_) {
       CHECK(ui::LinuxUi::instance());
       print_dialog_ = ui::LinuxUi::instance()->CreatePrintDialog(this);
diff --git a/printing/printing_context_linux.h b/printing/printing_context_linux.h
index 6fb35248..86ccebe 100644
--- a/printing/printing_context_linux.h
+++ b/printing/printing_context_linux.h
@@ -20,7 +20,7 @@
 // PrintingContext with optional native UI for print dialog and pdf_paper_size.
 class COMPONENT_EXPORT(PRINTING) PrintingContextLinux : public PrintingContext {
  public:
-  explicit PrintingContextLinux(Delegate* delegate);
+  PrintingContextLinux(Delegate* delegate, ProcessBehavior process_behavior);
   PrintingContextLinux(const PrintingContextLinux&) = delete;
   PrintingContextLinux& operator=(const PrintingContextLinux&) = delete;
   ~PrintingContextLinux() override;
diff --git a/printing/printing_context_mac.h b/printing/printing_context_mac.h
index c9a13ae..0b21e703 100644
--- a/printing/printing_context_mac.h
+++ b/printing/printing_context_mac.h
@@ -21,7 +21,7 @@
 
 class COMPONENT_EXPORT(PRINTING) PrintingContextMac : public PrintingContext {
  public:
-  explicit PrintingContextMac(Delegate* delegate);
+  PrintingContextMac(Delegate* delegate, ProcessBehavior process_behavior);
   PrintingContextMac(const PrintingContextMac&) = delete;
   PrintingContextMac& operator=(const PrintingContextMac&) = delete;
   ~PrintingContextMac() override;
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
index fab1e04..b051381 100644
--- a/printing/printing_context_mac.mm
+++ b/printing/printing_context_mac.mm
@@ -361,17 +361,13 @@
 // static
 std::unique_ptr<PrintingContext> PrintingContext::CreateImpl(
     Delegate* delegate,
-    bool skip_system_calls) {
-  auto context = std::make_unique<PrintingContextMac>(delegate);
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-  if (skip_system_calls)
-    context->set_skip_system_calls();
-#endif
-  return context;
+    ProcessBehavior process_behavior) {
+  return std::make_unique<PrintingContextMac>(delegate, process_behavior);
 }
 
-PrintingContextMac::PrintingContextMac(Delegate* delegate)
-    : PrintingContext(delegate),
+PrintingContextMac::PrintingContextMac(Delegate* delegate,
+                                       ProcessBehavior process_behavior)
+    : PrintingContext(delegate, process_behavior),
       print_info_([NSPrintInfo.sharedPrintInfo copy]) {}
 
 PrintingContextMac::~PrintingContextMac() {
@@ -427,7 +423,11 @@
         InitPrintSettingsFromPrintInfo();
         mojom::ResultCode result = mojom::ResultCode::kSuccess;
 #if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
-        if (features::ShouldPrintJobOop()) {
+        if (process_behavior() == ProcessBehavior::kOopEnabledSkipSystemCalls) {
+          // This is running in the browser process, where system calls are
+          // normally not allowed except for this system dialog exception.
+          // Capture the setting here to be transmitted to a PrintBackend
+          // service when the document is printed.
           result = CaptureSystemPrintDialogData(print_info_, settings_.get());
         }
 #endif
@@ -767,12 +767,19 @@
 
   in_print_job_ = true;
 
-  if (skip_system_calls())
+#if BUILDFLAG(ENABLE_OOP_PRINTING)
+  if (process_behavior() == ProcessBehavior::kOopEnabledSkipSystemCalls) {
     return mojom::ResultCode::kSuccess;
+  }
+#endif
 
 #if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
-  if (features::ShouldPrintJobOop() &&
+  if (process_behavior() == ProcessBehavior::kOopEnabledPerformSystemCalls &&
       !settings_->system_print_dialog_data().empty()) {
+    // Settings which the browser process captured from the system dialog now
+    // need to be applied to the printing context here which is running in a
+    // PrintBackend service.
+
     // NOTE: Reset `print_info_` with a copy of `sharedPrintInfo` so as to
     // start with a clean slate.
     print_info_ = [[NSPrintInfo sharedPrintInfo] copy];
diff --git a/printing/printing_context_no_system_dialog.cc b/printing/printing_context_no_system_dialog.cc
index 4809793..c6ca48a 100644
--- a/printing/printing_context_no_system_dialog.cc
+++ b/printing/printing_context_no_system_dialog.cc
@@ -23,13 +23,16 @@
 // static
 std::unique_ptr<PrintingContext> PrintingContext::CreateImpl(
     Delegate* delegate,
-    bool skip_system_calls) {
-  return std::make_unique<PrintingContextNoSystemDialog>(delegate);
+    ProcessBehavior process_behavior) {
+  return std::make_unique<PrintingContextNoSystemDialog>(delegate,
+                                                         process_behavior);
 }
 #endif  // !BUILDFLAG(USE_CUPS)
 
-PrintingContextNoSystemDialog::PrintingContextNoSystemDialog(Delegate* delegate)
-    : PrintingContext(delegate) {}
+PrintingContextNoSystemDialog::PrintingContextNoSystemDialog(
+    Delegate* delegate,
+    ProcessBehavior process_behavior)
+    : PrintingContext(delegate, process_behavior) {}
 
 PrintingContextNoSystemDialog::~PrintingContextNoSystemDialog() {
   ReleaseContext();
diff --git a/printing/printing_context_no_system_dialog.h b/printing/printing_context_no_system_dialog.h
index 92c4145c..b0dcf7f8 100644
--- a/printing/printing_context_no_system_dialog.h
+++ b/printing/printing_context_no_system_dialog.h
@@ -16,7 +16,8 @@
 class COMPONENT_EXPORT(PRINTING) PrintingContextNoSystemDialog
     : public PrintingContext {
  public:
-  explicit PrintingContextNoSystemDialog(Delegate* delegate);
+  PrintingContextNoSystemDialog(Delegate* delegate,
+                                ProcessBehavior process_behavior);
   PrintingContextNoSystemDialog(const PrintingContextNoSystemDialog&) = delete;
   PrintingContextNoSystemDialog& operator=(
       const PrintingContextNoSystemDialog&) = delete;
diff --git a/printing/printing_context_system_dialog_win.cc b/printing/printing_context_system_dialog_win.cc
index 8a7d9c1..391397c 100644
--- a/printing/printing_context_system_dialog_win.cc
+++ b/printing/printing_context_system_dialog_win.cc
@@ -15,15 +15,11 @@
 #include "printing/print_settings_initializer_win.h"
 #include "skia/ext/skia_utils_win.h"
 
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-#include "printing/printing_features.h"
-#endif
-
 namespace printing {
 
 HWND PrintingContextSystemDialogWin::GetWindow() {
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
-  if (features::ShouldPrintJobOop()) {
+  if (process_behavior() == ProcessBehavior::kOopEnabledPerformSystemCalls) {
     // Delving through the view tree to get to root window happens separately
     // in the browser process (i.e., not in `PrintingContextSystemDialogWin`)
     // before sending the identified window owner to the Print Backend service.
@@ -39,8 +35,9 @@
 }
 
 PrintingContextSystemDialogWin::PrintingContextSystemDialogWin(
-    Delegate* delegate)
-    : PrintingContextWin(delegate) {}
+    Delegate* delegate,
+    ProcessBehavior process_behavior)
+    : PrintingContextWin(delegate, process_behavior) {}
 
 PrintingContextSystemDialogWin::~PrintingContextSystemDialogWin() {}
 
diff --git a/printing/printing_context_system_dialog_win.h b/printing/printing_context_system_dialog_win.h
index d873d9dc..ca4a1ac 100644
--- a/printing/printing_context_system_dialog_win.h
+++ b/printing/printing_context_system_dialog_win.h
@@ -20,7 +20,8 @@
 class COMPONENT_EXPORT(PRINTING) PrintingContextSystemDialogWin
     : public PrintingContextWin {
  public:
-  explicit PrintingContextSystemDialogWin(Delegate* delegate);
+  PrintingContextSystemDialogWin(Delegate* delegate,
+                                 ProcessBehavior process_behavior);
   PrintingContextSystemDialogWin(const PrintingContextSystemDialogWin&) =
       delete;
   PrintingContextSystemDialogWin& operator=(
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index 82f82355..db75a04 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -78,18 +78,14 @@
 // static
 std::unique_ptr<PrintingContext> PrintingContext::CreateImpl(
     Delegate* delegate,
-    bool skip_system_calls) {
-  std::unique_ptr<PrintingContext> context;
-  context = std::make_unique<PrintingContextSystemDialogWin>(delegate);
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-  if (skip_system_calls)
-    context->set_skip_system_calls();
-#endif
-  return context;
+    ProcessBehavior process_behavior) {
+  return std::make_unique<PrintingContextSystemDialogWin>(delegate,
+                                                          process_behavior);
 }
 
-PrintingContextWin::PrintingContextWin(Delegate* delegate)
-    : PrintingContext(delegate), context_(nullptr) {}
+PrintingContextWin::PrintingContextWin(Delegate* delegate,
+                                       ProcessBehavior process_behavior)
+    : PrintingContext(delegate, process_behavior), context_(nullptr) {}
 
 PrintingContextWin::~PrintingContextWin() {
   ReleaseContext();
@@ -327,16 +323,24 @@
 mojom::ResultCode PrintingContextWin::NewDocument(
     const std::u16string& document_name) {
   DCHECK(!in_print_job_);
-  if (!context_ && !skip_system_calls())
+  if (!context_
+#if BUILDFLAG(ENABLE_OOP_PRINTING)
+      && process_behavior() != ProcessBehavior::kOopEnabledSkipSystemCalls
+#endif
+  ) {
     return OnError();
+  }
 
   // Set the flag used by the AbortPrintJob dialog procedure.
   abort_printing_ = false;
 
   in_print_job_ = true;
 
-  if (skip_system_calls())
+#if BUILDFLAG(ENABLE_OOP_PRINTING)
+  if (process_behavior() == ProcessBehavior::kOopEnabledSkipSystemCalls) {
     return mojom::ResultCode::kSuccess;
+  }
+#endif
 
   if (base::FeatureList::IsEnabled(printing::features::kUseXpsForPrinting)) {
     // This is all the new document context needed when using XPS.
diff --git a/printing/printing_context_win.h b/printing/printing_context_win.h
index b4d969d0..f3babb9 100644
--- a/printing/printing_context_win.h
+++ b/printing/printing_context_win.h
@@ -20,7 +20,7 @@
 
 class COMPONENT_EXPORT(PRINTING) PrintingContextWin : public PrintingContext {
  public:
-  explicit PrintingContextWin(Delegate* delegate);
+  PrintingContextWin(Delegate* delegate, ProcessBehavior process_behavior);
   PrintingContextWin(const PrintingContextWin&) = delete;
   PrintingContextWin& operator=(const PrintingContextWin&) = delete;
   ~PrintingContextWin() override;
diff --git a/printing/printing_context_win_unittest.cc b/printing/printing_context_win_unittest.cc
index d55e5ab7..4398dbe 100644
--- a/printing/printing_context_win_unittest.cc
+++ b/printing/printing_context_win_unittest.cc
@@ -58,8 +58,10 @@
 
 class MockPrintingContextWin : public PrintingContextSystemDialogWin {
  public:
-  explicit MockPrintingContextWin(Delegate* delegate)
-      : PrintingContextSystemDialogWin(delegate) {}
+  MockPrintingContextWin(Delegate* delegate)
+      : PrintingContextSystemDialogWin(
+            delegate,
+            PrintingContext::ProcessBehavior::kOopDisabled) {}
 
  protected:
   // This is a fake PrintDlgEx implementation that sets the right fields in
@@ -183,7 +185,8 @@
   auto settings = std::make_unique<PrintSettings>();
   settings->set_device_name(base::WideToUTF16(GetDefaultPrinter()));
   // Initialize it.
-  PrintingContextWin context(this);
+  PrintingContextWin context(this,
+                             PrintingContext::ProcessBehavior::kOopDisabled);
   EXPECT_EQ(mojom::ResultCode::kSuccess,
             context.InitWithSettingsForTest(std::move(settings)));
 
diff --git a/printing/test_printing_context.cc b/printing/test_printing_context.cc
index da8055a..8eca2dfa 100644
--- a/printing/test_printing_context.cc
+++ b/printing/test_printing_context.cc
@@ -43,13 +43,8 @@
 }
 
 TestPrintingContext::TestPrintingContext(Delegate* delegate,
-                                         bool skip_system_calls)
-    : PrintingContext(delegate) {
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-  if (skip_system_calls)
-    set_skip_system_calls();
-#endif
-}
+                                         ProcessBehavior process_behavior)
+    : PrintingContext(delegate, process_behavior) {}
 
 TestPrintingContext::~TestPrintingContext() = default;
 
@@ -185,7 +180,7 @@
   DCHECK(!in_print_job_);
 
 #if BUILDFLAG(ENABLE_OOP_PRINTING_NO_OOP_BASIC_PRINT_DIALOG)
-  if (!skip_system_calls() && features::ShouldPrintJobOop() &&
+  if (process_behavior() == ProcessBehavior::kOopEnabledPerformSystemCalls &&
       !settings_->system_print_dialog_data().empty()) {
     // Mimic the update when system print dialog settings are provided to
     // Print Backend service from the browser process.
@@ -204,7 +199,13 @@
   abort_printing_ = false;
   in_print_job_ = true;
 
-  if (!skip_system_calls()) {
+#if BUILDFLAG(ENABLE_OOP_PRINTING)
+  const bool make_system_calls =
+      process_behavior() != ProcessBehavior::kOopEnabledSkipSystemCalls;
+#else
+  const bool make_system_calls = true;
+#endif
+  if (make_system_calls) {
     if (new_document_cancels_) {
       return mojom::ResultCode::kCanceled;
     }
diff --git a/printing/test_printing_context.h b/printing/test_printing_context.h
index 5750134..1db95b6 100644
--- a/printing/test_printing_context.h
+++ b/printing/test_printing_context.h
@@ -45,7 +45,7 @@
 #endif
       const PrintSettings&)>;
 
-  TestPrintingContext(Delegate* delegate, bool skip_system_calls);
+  TestPrintingContext(Delegate* delegate, ProcessBehavior process_behavior);
   TestPrintingContext(const TestPrintingContext&) = delete;
   TestPrintingContext& operator=(const TestPrintingContext&) = delete;
   ~TestPrintingContext() override;
diff --git a/remoting/host/chromeos/remote_support_host_ash.cc b/remoting/host/chromeos/remote_support_host_ash.cc
index aa7c5fa..fd3a835 100644
--- a/remoting/host/chromeos/remote_support_host_ash.cc
+++ b/remoting/host/chromeos/remote_support_host_ash.cc
@@ -19,10 +19,10 @@
 #include "remoting/host/chromeos/features.h"
 #include "remoting/host/chromeos/session_storage.h"
 #include "remoting/host/chromoting_host_context.h"
-#include "remoting/host/it2me/connection_details.h"
 #include "remoting/host/it2me/it2me_constants.h"
 #include "remoting/host/it2me/it2me_host.h"
 #include "remoting/host/it2me/it2me_native_messaging_host_ash.h"
+#include "remoting/host/it2me/reconnect_params.h"
 #include "remoting/host/policy_watcher.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -32,32 +32,15 @@
 
 using remoting::features::kEnableCrdAdminRemoteAccessV2;
 
-constexpr char kEnterpriseParamsDictKey[] = "enterprise-params";
-constexpr char kSuppressUserDialogsKey[] = "suppress-user-dialogs";
-constexpr char kSuppressNotificationsKey[] = "suppress-notifications";
-constexpr char kTerminateUponInputKey[] = "terminate-upon-input";
-constexpr char kCurtainLocalUserSessionKey[] = "curtain-local-user-session";
-constexpr char kShowTroubleshootingToolsKey[] = "show-troubleshooting-tools";
-constexpr char kAllowTroubleshootingToolsKey[] = "allow-troubleshooting-tools";
-constexpr char kAllowReconnections[] = "allow-reconnections";
-constexpr char kAllowFileTransfer[] = "allow-file-transfer";
-
-constexpr char kSessionParamsDictKey[] = "session-params";
-constexpr char kUserNameKey[] = "user-name";
-constexpr char kOauthTokenKey[] = "oauth-token";
-
-constexpr char kReconnectParamsDictKey[] = "reconnect-params";
-constexpr char kRemoteUsernameKey[] = "remote-username";
-
 base::Value::Dict EnterpriseParamsToDict(
     const ChromeOsEnterpriseParams& params) {
   return base::Value::Dict()
-      .Set(kSuppressUserDialogsKey, params.suppress_user_dialogs)
-      .Set(kSuppressNotificationsKey, params.suppress_notifications)
-      .Set(kTerminateUponInputKey, params.terminate_upon_input)
-      .Set(kCurtainLocalUserSessionKey, params.curtain_local_user_session)
-      .Set(kShowTroubleshootingToolsKey, params.show_troubleshooting_tools)
-      .Set(kAllowTroubleshootingToolsKey, params.allow_troubleshooting_tools)
+      .Set(kSuppressUserDialogs, params.suppress_user_dialogs)
+      .Set(kSuppressNotifications, params.suppress_notifications)
+      .Set(kTerminateUponInput, params.terminate_upon_input)
+      .Set(kCurtainLocalUserSession, params.curtain_local_user_session)
+      .Set(kShowTroubleshootingTools, params.show_troubleshooting_tools)
+      .Set(kAllowTroubleshootingTools, params.allow_troubleshooting_tools)
       .Set(kAllowReconnections, params.allow_reconnections)
       .Set(kAllowFileTransfer, params.allow_file_transfer);
 }
@@ -65,16 +48,15 @@
 ChromeOsEnterpriseParams EnterpriseParamsFromDict(
     const base::Value::Dict& dict) {
   return ChromeOsEnterpriseParams{
-      .suppress_user_dialogs = dict.FindBool(kSuppressUserDialogsKey).value(),
-      .suppress_notifications =
-          dict.FindBool(kSuppressNotificationsKey).value(),
-      .terminate_upon_input = dict.FindBool(kTerminateUponInputKey).value(),
+      .suppress_user_dialogs = dict.FindBool(kSuppressUserDialogs).value(),
+      .suppress_notifications = dict.FindBool(kSuppressNotifications).value(),
+      .terminate_upon_input = dict.FindBool(kTerminateUponInput).value(),
       .curtain_local_user_session =
-          dict.FindBool(kCurtainLocalUserSessionKey).value(),
+          dict.FindBool(kCurtainLocalUserSession).value(),
       .show_troubleshooting_tools =
-          dict.FindBool(kShowTroubleshootingToolsKey).value(),
+          dict.FindBool(kShowTroubleshootingTools).value(),
       .allow_troubleshooting_tools =
-          dict.FindBool(kAllowTroubleshootingToolsKey).value(),
+          dict.FindBool(kAllowTroubleshootingTools).value(),
       .allow_reconnections = dict.FindBool(kAllowReconnections).value(),
       .allow_file_transfer = dict.FindBool(kAllowFileTransfer).value(),
   };
@@ -82,28 +64,23 @@
 
 base::Value::Dict SessionParamsToDict(
     const mojom::SupportSessionParams& params) {
-  return base::Value::Dict()
-      .Set(kUserNameKey, params.user_name)
-      .Set(kOauthTokenKey, params.oauth_access_token);
+  auto session_params = base::Value::Dict()
+                            .Set(kUserName, params.user_name)
+                            .Set(kAuthorizedHelper, *params.authorized_helper);
+
+  return session_params;
 }
 
 mojom::SupportSessionParams SessionParamsFromDict(
     const base::Value::Dict& dict) {
   mojom::SupportSessionParams result;
-  result.user_name = *dict.FindString(kUserNameKey);
-  result.oauth_access_token = *dict.FindString(kOauthTokenKey);
+  result.user_name = *dict.FindString(kUserName);
+  result.authorized_helper = *dict.FindString(kAuthorizedHelper);
   return result;
 }
 
-base::Value::Dict ConnectionDetailsToDict(const ConnectionDetails& details) {
-  return base::Value::Dict().Set(kRemoteUsernameKey, details.remote_username);
-}
-
-ConnectionDetails ConnectionDetailsFromDict(const base::Value::Dict& dict) {
-  return {.remote_username = *dict.FindString(kRemoteUsernameKey)};
-}
-
 mojom::StartSupportSessionResponsePtr GetUnableToReconnectError() {
+  // TODO(joedow): Add better error messages.
   return mojom::StartSupportSessionResponse::NewSupportSessionError(
       mojom::StartSupportSessionError::kUnknown);
 }
@@ -139,7 +116,7 @@
 void RemoteSupportHostAsh::StartSession(
     const mojom::SupportSessionParams& params,
     const absl::optional<ChromeOsEnterpriseParams>& enterprise_params,
-    const absl::optional<ConnectionDetails>& reconnect_params,
+    const absl::optional<ReconnectParams>& reconnect_params,
     StartSessionCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -212,11 +189,11 @@
 
         LOG(INFO) << "CRD: Reconnectable session found - starting connection";
         self->StartSession(
-            SessionParamsFromDict(*session->EnsureDict(kSessionParamsDictKey)),
+            SessionParamsFromDict(*session->EnsureDict(kSessionParamsDict)),
             EnterpriseParamsFromDict(
-                *session->EnsureDict(kEnterpriseParamsDictKey)),
-            ConnectionDetailsFromDict(
-                *session->EnsureDict(kReconnectParamsDictKey)),
+                *session->EnsureDict(kEnterpriseParamsDict)),
+            ReconnectParams::FromDict(
+                *session->EnsureDict(kReconnectParamsDict)),
             std::move(callback));
       },
       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
@@ -230,23 +207,27 @@
 }
 
 void RemoteSupportHostAsh::OnHostStateConnected(
-    mojom::SupportSessionParams params,
+    mojom::SupportSessionParams session_params,
     absl::optional<ChromeOsEnterpriseParams> enterprise_params,
-    ConnectionDetails details) {
+    absl::optional<ReconnectParams> reconnect_params) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!base::FeatureList::IsEnabled(kEnableCrdAdminRemoteAccessV2)) {
     return;
   }
 
-  if (enterprise_params.has_value() && enterprise_params->allow_reconnections) {
+  if (reconnect_params.has_value()) {
+    CHECK(enterprise_params.has_value());
+    CHECK(enterprise_params->allow_reconnections);
+
     LOG(INFO) << "CRD: Storing information for reconnectable session";
     session_storage_->StoreSession(
         base::Value::Dict()
-            .Set(kReconnectParamsDictKey, ConnectionDetailsToDict(details))
-            .Set(kSessionParamsDictKey, SessionParamsToDict(params))
-            .Set(kEnterpriseParamsDictKey,
-                 EnterpriseParamsToDict(*enterprise_params)),
+            .Set(kSessionParamsDict, SessionParamsToDict(session_params))
+            .Set(kEnterpriseParamsDict,
+                 EnterpriseParamsToDict(*enterprise_params))
+            .Set(kReconnectParamsDict,
+                 ReconnectParams::ToDict(*reconnect_params)),
         base::DoNothing());
     return;
   }
diff --git a/remoting/host/chromeos/remote_support_host_ash.h b/remoting/host/chromeos/remote_support_host_ash.h
index 9dd56a0..791eaa6 100644
--- a/remoting/host/chromeos/remote_support_host_ash.h
+++ b/remoting/host/chromeos/remote_support_host_ash.h
@@ -67,12 +67,12 @@
   void StartSession(
       const mojom::SupportSessionParams& params,
       const absl::optional<ChromeOsEnterpriseParams>& enterprise_params,
-      const absl::optional<ConnectionDetails>& reconnect_params,
+      const absl::optional<ReconnectParams>& reconnect_params,
       StartSessionCallback callback);
 
   void OnHostStateConnected(mojom::SupportSessionParams,
                             absl::optional<ChromeOsEnterpriseParams>,
-                            ConnectionDetails details);
+                            absl::optional<ReconnectParams>);
   void OnHostStateDisconnected();
   void OnSessionDisconnected();
 
diff --git a/remoting/host/chromeos/remote_support_host_ash_unittest.cc b/remoting/host/chromeos/remote_support_host_ash_unittest.cc
index 1d1482b5..5d44226f 100644
--- a/remoting/host/chromeos/remote_support_host_ash_unittest.cc
+++ b/remoting/host/chromeos/remote_support_host_ash_unittest.cc
@@ -33,6 +33,8 @@
 using base::test::TestFuture;
 using remoting::features::kEnableCrdAdminRemoteAccessV2;
 
+constexpr char kRemoteAdminEmail[] = "admin@domain.com";
+
 // Matcher that checks if the result of a `StartSupportSession` request
 // indicates we failed to start the session
 auto IsError() {
@@ -68,10 +70,6 @@
     connect_waiter_.SetValue();
   }
   void Disconnect() override {}
-  void set_chrome_os_enterprise_params(
-      ChromeOsEnterpriseParams value) override {
-    enterprise_params_ = value;
-  }
 
   bool WaitForConnectCall() {
     bool success = connect_waiter_.Wait();
@@ -80,8 +78,8 @@
   }
 
   std::string user_name() const { return user_name_; }
-  ChromeOsEnterpriseParams enterprise_params() const {
-    return enterprise_params_;
+  const ChromeOsEnterpriseParams& enterprise_params() const {
+    return chrome_os_enterprise_params();
   }
 
   It2MeHost::Observer& observer() {
@@ -96,7 +94,6 @@
 
   base::WeakPtr<It2MeHost::Observer> observer_;
   std::string user_name_;
-  ChromeOsEnterpriseParams enterprise_params_;
   TestFuture<void> connect_waiter_;
 };
 
@@ -216,6 +213,8 @@
   mojom::SupportSessionParams GetSupportSessionParams() {
     mojom::SupportSessionParams params;
     params.user_name = "<the-user>";
+    params.oauth_access_token = "oauth2: VALID_ACCESS_TOKEN";
+    params.authorized_helper = kRemoteAdminEmail;
     return params;
   }
 
@@ -260,10 +259,9 @@
 
   bool StoreReconnectableSessionInformation(
       mojom::SupportSessionParams params,
-      ChromeOsEnterpriseParams enterprise_params = {.allow_reconnections =
-                                                        true},
-      std::string remote_user_email = "remote-user@email.com") {
-    // Only reconnectable sessions can be stored as reconnectable sessions.
+      ChromeOsEnterpriseParams enterprise_params = {
+          .allow_reconnections = true}) {
+    // Reconnectable sessions can only be stored if reconnections are allowed.
     CHECK(enterprise_params.allow_reconnections);
 
     // We do not want our test to make any assumptions about how the
@@ -278,7 +276,7 @@
 
     support_host.StartSession(params, enterprise_params, base::DoNothing());
     EXPECT_TRUE(it2me_host->WaitForConnectCall());
-    it2me_host->observer().OnClientAuthenticated(remote_user_email);
+    it2me_host->observer().OnClientAuthenticated(kRemoteAdminEmail);
     it2me_host->observer().OnStateChanged(It2MeHostState::kConnected,
                                           protocol::ErrorCode::OK);
 
@@ -641,12 +639,11 @@
   EnableFeature(kEnableCrdAdminRemoteAccessV2);
 
   ASSERT_TRUE(StoreReconnectableSessionInformation(
-      GetSupportSessionParams(), {.allow_reconnections = true},
-      "the-remote-user@domain.com"));
+      GetSupportSessionParams(), {.allow_reconnections = true}));
 
   ReconnectToSession(kEnterpriseSessionId);
 
-  EXPECT_EQ(it2me_host().authorized_helper(), "the-remote-user@domain.com");
+  EXPECT_EQ(it2me_host().authorized_helper(), kRemoteAdminEmail);
 }
 
 TEST_F(RemoteSupportHostAshTest,
diff --git a/remoting/host/it2me/BUILD.gn b/remoting/host/it2me/BUILD.gn
index efa6e01..2c57a60c 100644
--- a/remoting/host/it2me/BUILD.gn
+++ b/remoting/host/it2me/BUILD.gn
@@ -39,7 +39,6 @@
 
 source_set("common") {
   sources = [
-    "connection_details.h",
     "it2me_confirmation_dialog.h",
     "it2me_confirmation_dialog_proxy.cc",
     "it2me_confirmation_dialog_proxy.h",
@@ -47,6 +46,8 @@
     "it2me_host.h",
     "it2me_native_messaging_host.cc",
     "it2me_native_messaging_host.h",
+    "reconnect_params.cc",
+    "reconnect_params.h",
   ]
 
   deps = []
diff --git a/remoting/host/it2me/connection_details.h b/remoting/host/it2me/connection_details.h
deleted file mode 100644
index 24b59df..0000000
--- a/remoting/host/it2me/connection_details.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef REMOTING_HOST_IT2ME_CONNECTION_DETAILS_H_
-#define REMOTING_HOST_IT2ME_CONNECTION_DETAILS_H_
-
-#include <string>
-
-namespace remoting {
-
-struct ConnectionDetails {
-  std::string remote_username;
-};
-
-}  // namespace remoting
-
-#endif  // REMOTING_HOST_IT2ME_CONNECTION_DETAILS_H_
diff --git a/remoting/host/it2me/it2me_constants.cc b/remoting/host/it2me/it2me_constants.cc
index 63c42f6..938a11a 100644
--- a/remoting/host/it2me/it2me_constants.cc
+++ b/remoting/host/it2me/it2me_constants.cc
@@ -64,4 +64,15 @@
 
 const char kPolicyErrorMessage[] = "policyError";
 
+const char kSessionParamsDict[] = "sessionParamsDict";
+
+const char kEnterpriseParamsDict[] = "enterpriseParamsDict";
+
+const char kReconnectParamsDict[] = "reconnectParamsDict";
+const char kReconnectSupportId[] = "reconnectSupportId";
+const char kReconnectHostSecret[] = "reconnectHostSecret";
+const char kReconnectPrivateKey[] = "reconnectPrivateKey";
+const char kReconnectFtlDeviceRegistrationId[] =
+    "reconnectFtlDeviceRegistrationId";
+
 }  // namespace remoting
diff --git a/remoting/host/it2me/it2me_constants.h b/remoting/host/it2me/it2me_constants.h
index 0f0fa71..59aad34 100644
--- a/remoting/host/it2me/it2me_constants.h
+++ b/remoting/host/it2me/it2me_constants.h
@@ -110,6 +110,15 @@
 // Sent from the host when there is a problem reading the local policy.
 extern const char kPolicyErrorMessage[];
 
+// Keys used for storing and retrieving params used for reconnectable sessions.
+extern const char kSessionParamsDict[];
+extern const char kEnterpriseParamsDict[];
+extern const char kReconnectParamsDict[];
+extern const char kReconnectSupportId[];
+extern const char kReconnectHostSecret[];
+extern const char kReconnectPrivateKey[];
+extern const char kReconnectFtlDeviceRegistrationId[];
+
 }  // namespace remoting
 
 #endif  // REMOTING_HOST_IT2ME_IT2ME_CONSTANTS_H_
diff --git a/remoting/host/it2me/it2me_host.h b/remoting/host/it2me/it2me_host.h
index caf7642..7c70e5ff 100644
--- a/remoting/host/it2me/it2me_host.h
+++ b/remoting/host/it2me/it2me_host.h
@@ -93,8 +93,12 @@
 
   // Session parameters provided by the remote command infrastructure when the
   // session is started from the admin console for a managed Chrome OS device.
-  virtual void set_chrome_os_enterprise_params(ChromeOsEnterpriseParams params);
-
+  void set_chrome_os_enterprise_params(ChromeOsEnterpriseParams params);
+  // Callers should call is_enterprise_session() first to ensure the params are
+  // present and retrievable.
+  const ChromeOsEnterpriseParams& chrome_os_enterprise_params() const {
+    return *chrome_os_enterprise_params_;
+  }
   // Indicates whether this support session was initiated by the admin console
   // for a managed Chrome OS device.
   bool is_enterprise_session() const {
diff --git a/remoting/host/it2me/it2me_native_messaging_host.cc b/remoting/host/it2me/it2me_native_messaging_host.cc
index 82bc589..1de66dc 100644
--- a/remoting/host/it2me/it2me_native_messaging_host.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host.cc
@@ -495,10 +495,24 @@
                   static_cast<int>(access_code_lifetime_.InSeconds()));
       break;
 
-    case It2MeHostState::kConnected:
+    case It2MeHostState::kConnected: {
       message.Set(kClient, client_username_);
-      break;
 
+      if (it2me_host_->is_enterprise_session() &&
+          it2me_host_->chrome_os_enterprise_params().allow_reconnections) {
+        // These test values are needed so the impl CL can be broken up into
+        // smaller patchsets.
+        // TODO(joedow): Replace them with real values.
+        message.Set(kReconnectParamsDict,
+                    base::Value::Dict()
+                        .Set(kReconnectSupportId, "1234567")
+                        .Set(kReconnectHostSecret, "12345")
+                        .Set(kReconnectPrivateKey, std::string(384, 'a'))
+                        .Set(kReconnectFtlDeviceRegistrationId,
+                             "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"));
+      }
+      break;
+    }
     case It2MeHostState::kDisconnected:
       message.Set(kDisconnectReason, ErrorCodeToString(error_code));
       client_username_.clear();
diff --git a/remoting/host/it2me/it2me_native_messaging_host_ash.cc b/remoting/host/it2me/it2me_native_messaging_host_ash.cc
index 993bbbe..3edceec 100644
--- a/remoting/host/it2me/it2me_native_messaging_host_ash.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host_ash.cc
@@ -16,8 +16,8 @@
 #include "remoting/host/chromeos/chromeos_enterprise_params.h"
 #include "remoting/host/chromeos/features.h"
 #include "remoting/host/chromoting_host_context.h"
-#include "remoting/host/it2me/connection_details.h"
 #include "remoting/host/it2me/it2me_native_messaging_host.h"
+#include "remoting/host/it2me/reconnect_params.h"
 #include "remoting/host/native_messaging/native_messaging_helpers.h"
 #include "remoting/host/policy_watcher.h"
 
@@ -154,7 +154,7 @@
 void It2MeNativeMessageHostAsh::Connect(
     const mojom::SupportSessionParams& params,
     const absl::optional<ChromeOsEnterpriseParams>& enterprise_params,
-    const absl::optional<ConnectionDetails>& reconnect_params,
+    const absl::optional<ReconnectParams>& reconnect_params,
     base::OnceClosure connected_callback,
     HostStateConnectedCallback host_state_connected_callback,
     base::OnceClosure host_state_disconnected_callback,
@@ -195,15 +195,9 @@
   }
 
   if (reconnect_params.has_value()) {
-    // We pass the previously connected user as the `authorized_helper`, to
+    // We persist the previously connected user as the `authorized_helper`, to
     // prevent anyone else from snooping in and connecting to the session.
-    message.Set(kAuthorizedHelper, reconnect_params.value().remote_username);
-
-    if (params.authorized_helper.has_value()) {
-      // Check we did not receive conflicting information.
-      CHECK_EQ(params.authorized_helper.value(),
-               reconnect_params.value().remote_username);
-    }
+    CHECK(params.authorized_helper.has_value());
 
     // TODO(b/283091055): Send the reconnection params in the connect message,
     // and use them to reconnect to an existing client.
@@ -333,11 +327,20 @@
     }
     remote_->OnHostStateConnected(*remote_username);
 
-    // TODO(b/283091055): Update the client connected response to contain
-    // reconnection information (if the session is reconnectable), and add
-    // this information to `ConnectionDetail`.
-    std::move(host_state_connected_callback_)
-        .Run(ConnectionDetails(*remote_username));
+    absl::optional<ReconnectParams> reconnect_params;
+    const auto* reconnect_params_ptr = message.FindDict(kReconnectParamsDict);
+    if (reconnect_params_ptr) {
+      reconnect_params.emplace();
+      reconnect_params->support_id =
+          *reconnect_params_ptr->FindString(kReconnectSupportId);
+      reconnect_params->host_secret =
+          *reconnect_params_ptr->FindString(kReconnectHostSecret);
+      reconnect_params->private_key =
+          *reconnect_params_ptr->FindString(kReconnectPrivateKey);
+      reconnect_params->ftl_device_registration_id =
+          *reconnect_params_ptr->FindString(kReconnectFtlDeviceRegistrationId);
+    }
+    std::move(host_state_connected_callback_).Run(std::move(reconnect_params));
 
   } else if (*new_state == kHostStateError) {
     const std::string* error_code_string =
diff --git a/remoting/host/it2me/it2me_native_messaging_host_ash.h b/remoting/host/it2me/it2me_native_messaging_host_ash.h
index cbd0e7d7..51cbf43 100644
--- a/remoting/host/it2me/it2me_native_messaging_host_ash.h
+++ b/remoting/host/it2me/it2me_native_messaging_host_ash.h
@@ -27,7 +27,7 @@
 class It2MeHostFactory;
 class PolicyWatcher;
 struct ChromeOsEnterpriseParams;
-struct ConnectionDetails;
+struct ReconnectParams;
 
 // This class wraps the It2MeNativeMessageHost instance used on other platforms
 // and provides a way to interact with it using Mojo IPC.  This instance
@@ -45,7 +45,7 @@
   ~It2MeNativeMessageHostAsh() override;
 
   using HostStateConnectedCallback =
-      base::OnceCallback<void(ConnectionDetails)>;
+      base::OnceCallback<void(absl::optional<ReconnectParams>)>;
 
   // Creates a new NMH instance, creates a new SupportHostObserver remote and
   // returns the pending_remote.  Start() must be called before the first call
@@ -65,7 +65,7 @@
   void Connect(
       const mojom::SupportSessionParams& params,
       const absl::optional<ChromeOsEnterpriseParams>& enterprise_params,
-      const absl::optional<ConnectionDetails>& reconnect_params,
+      const absl::optional<ReconnectParams>& reconnect_params,
       base::OnceClosure connected_callback,
       HostStateConnectedCallback host_state_connected_callback,
       base::OnceClosure host_state_disconnected_callback,
diff --git a/remoting/host/it2me/reconnect_params.cc b/remoting/host/it2me/reconnect_params.cc
new file mode 100644
index 0000000..702b77e
--- /dev/null
+++ b/remoting/host/it2me/reconnect_params.cc
@@ -0,0 +1,79 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/it2me/reconnect_params.h"
+
+#include "base/check.h"
+#include "base/logging.h"
+#include "base/uuid.h"
+#include "remoting/host/it2me/it2me_constants.h"
+
+namespace remoting {
+
+ReconnectParams::ReconnectParams() = default;
+ReconnectParams::ReconnectParams(ReconnectParams&& other) = default;
+ReconnectParams& ReconnectParams::operator=(ReconnectParams&& other) = default;
+ReconnectParams::~ReconnectParams() = default;
+
+base::Value::Dict ReconnectParams::ToDict(const ReconnectParams& params) {
+  DCHECK(params.IsValid());
+  return base::Value::Dict()
+      .Set(kReconnectSupportId, params.support_id)
+      .Set(kReconnectHostSecret, params.host_secret)
+      .Set(kReconnectPrivateKey, params.private_key)
+      .Set(kReconnectFtlDeviceRegistrationId,
+           params.ftl_device_registration_id);
+}
+
+ReconnectParams ReconnectParams::FromDict(const base::Value::Dict& dict) {
+  ReconnectParams params;
+  params.support_id = *dict.FindString(kReconnectSupportId);
+  params.host_secret = *dict.FindString(kReconnectHostSecret);
+  params.private_key = *dict.FindString(kReconnectPrivateKey);
+  params.ftl_device_registration_id =
+      *dict.FindString(kReconnectFtlDeviceRegistrationId);
+
+  DCHECK(params.IsValid());
+  return params;
+}
+
+bool ReconnectParams::IsValid() const {
+  if (support_id.empty()) {
+    LOG(WARNING) << "Missing field: support_id";
+    return false;
+  } else if (support_id.length() != 7) {
+    LOG(WARNING) << "Invalid support_id: " << support_id;
+    return false;
+  }
+
+  if (host_secret.empty()) {
+    LOG(WARNING) << "Missing field: host_secret";
+    return false;
+  } else if (host_secret.length() != 5) {
+    LOG(WARNING) << "Invalid host_secret: " << host_secret;
+    return false;
+  }
+
+  if (private_key.empty()) {
+    LOG(WARNING) << "Missing field: private_key";
+    return false;
+  } else if (private_key.length() != 384) {
+    LOG(WARNING) << "Invalid private_key length: " << private_key.length();
+    return false;
+  }
+
+  if (ftl_device_registration_id.empty()) {
+    LOG(WARNING) << "Missing field: ftl_device_registration_id";
+    return false;
+  } else if (!base::Uuid::ParseLowercase(ftl_device_registration_id)
+                  .is_valid()) {
+    LOG(WARNING) << "Invalid ftl_device_registration_id: "
+                 << ftl_device_registration_id;
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace remoting
diff --git a/remoting/host/it2me/reconnect_params.h b/remoting/host/it2me/reconnect_params.h
new file mode 100644
index 0000000..a77d6867
--- /dev/null
+++ b/remoting/host/it2me/reconnect_params.h
@@ -0,0 +1,42 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_IT2ME_RECONNECT_PARAMS_H_
+#define REMOTING_HOST_IT2ME_RECONNECT_PARAMS_H_
+
+#include <string>
+
+#include "base/values.h"
+
+namespace remoting {
+
+struct ReconnectParams {
+  ReconnectParams();
+  ReconnectParams(ReconnectParams&& other);
+  ReconnectParams& operator=(ReconnectParams&& other);
+  ~ReconnectParams();
+
+  // Helpers used to convert to/from a JSON dictionary.
+  static base::Value::Dict ToDict(const ReconnectParams& params);
+  static ReconnectParams FromDict(const base::Value::Dict& dict);
+
+  // Verifies the structure contains valid data.
+  bool IsValid() const;
+
+  // The 7 digit host identifier used for Directory registration and lookups.
+  std::string support_id;
+
+  // The 5 digit host 'secret' used to establish a secure P2P connection.
+  std::string host_secret;
+
+  // A Base64 encoded string representing the host's private key.
+  std::string private_key;
+
+  // A UUID representing an endpoint in the FTL signaling service.
+  std::string ftl_device_registration_id;
+};
+
+}  // namespace remoting
+
+#endif  // REMOTING_HOST_IT2ME_RECONNECT_PARAMS_H_
diff --git a/sandbox/policy/BUILD.gn b/sandbox/policy/BUILD.gn
index 256e4c4..0797ed2 100644
--- a/sandbox/policy/BUILD.gn
+++ b/sandbox/policy/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 import("//chromeos/ash/components/assistant/assistant.gni")
diff --git a/services/audio/BUILD.gn b/services/audio/BUILD.gn
index c3ebab2d..2270da2 100644
--- a/services/audio/BUILD.gn
+++ b/services/audio/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//media/media_options.gni")
 import("//testing/test.gni")
diff --git a/services/device/generic_sensor/generic_sensor_service_unittest.cc b/services/device/generic_sensor/generic_sensor_service_unittest.cc
index bdcac77..0f28d5d 100644
--- a/services/device/generic_sensor/generic_sensor_service_unittest.cc
+++ b/services/device/generic_sensor/generic_sensor_service_unittest.cc
@@ -167,16 +167,13 @@
  protected:
   mojom::CreateVirtualSensorResult CreateVirtualSensorSync(SensorType type) {
     auto metadata = mojom::VirtualSensorMetadata::New();
-    metadata->maximum_frequency =
-        mojom::NullableDouble::New(kMaximumPlatformFrequency);
-    metadata->minimum_frequency =
-        mojom::NullableDouble::New(kMinimumPlatformFrequency);
+    metadata->maximum_frequency = kMaximumPlatformFrequency;
+    metadata->minimum_frequency = kMinimumPlatformFrequency;
 
     // Make all sensor types have the same reporting mode for the tests to work
     // as expected here (i.e. TestSensorClient::SensorReadingChanged() works
     // reliably).
-    metadata->reporting_mode =
-        mojom::NullableReportingMode::New(mojom::ReportingMode::ON_CHANGE);
+    metadata->reporting_mode = mojom::ReportingMode::ON_CHANGE;
 
     base::test::TestFuture<mojom::CreateVirtualSensorResult> future;
     sensor_provider_->CreateVirtualSensor(type, std::move(metadata),
diff --git a/services/device/generic_sensor/virtual_platform_sensor_provider.cc b/services/device/generic_sensor/virtual_platform_sensor_provider.cc
index 811f3c5..cc55d96 100644
--- a/services/device/generic_sensor/virtual_platform_sensor_provider.cc
+++ b/services/device/generic_sensor/virtual_platform_sensor_provider.cc
@@ -59,14 +59,16 @@
 
   auto sensor =
       base::MakeRefCounted<VirtualPlatformSensor>(type, reading_buffer, this);
-  if (!metadata->minimum_frequency.is_null()) {
-    sensor->set_minimum_supported_frequency(metadata->minimum_frequency->value);
+  if (metadata->minimum_frequency.has_value()) {
+    sensor->set_minimum_supported_frequency(
+        metadata->minimum_frequency.value());
   }
-  if (!metadata->maximum_frequency.is_null()) {
-    sensor->set_maximum_supported_frequency(metadata->maximum_frequency->value);
+  if (metadata->maximum_frequency.has_value()) {
+    sensor->set_maximum_supported_frequency(
+        metadata->maximum_frequency.value());
   }
-  if (!metadata->reporting_mode.is_null()) {
-    sensor->set_reporting_mode(metadata->reporting_mode->value);
+  if (metadata->reporting_mode.has_value()) {
+    sensor->set_reporting_mode(metadata->reporting_mode.value());
   }
   std::move(callback).Run(std::move(sensor));
 }
diff --git a/services/device/geolocation/network_location_request.cc b/services/device/geolocation/network_location_request.cc
index da46739..4517a5a 100644
--- a/services/device/geolocation/network_location_request.cc
+++ b/services/device/geolocation/network_location_request.cc
@@ -86,14 +86,6 @@
                            code);
 }
 
-void RecordUmaAccessPoints(int count) {
-  const int min = 1;
-  const int max = 20;
-  const int buckets = 21;
-  UMA_HISTOGRAM_CUSTOM_COUNTS("Geolocation.NetworkLocationRequest.AccessPoints",
-                              count, min, max, buckets);
-}
-
 void RecordUmaRequestInterval(base::TimeDelta time_delta) {
   const int kMin = 1;
   const int kMax = 11;
@@ -202,7 +194,6 @@
       << "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";
diff --git a/services/device/public/mojom/sensor_provider.mojom b/services/device/public/mojom/sensor_provider.mojom
index 39ef2c5..ebcfe4c 100644
--- a/services/device/public/mojom/sensor_provider.mojom
+++ b/services/device/public/mojom/sensor_provider.mojom
@@ -65,28 +65,14 @@
   GetVirtualSensorInformationError error;
 };
 
-// TODO(crbug.com/657632): Mojo does not allow primitive types to be nullable,
-// so we need to define a few wrapper structs.
-// Optional double field.
-struct NullableDouble {
-  // The value of the double.
-  double value;
-};
-
-// Optional ReportingMode field.
-struct NullableReportingMode {
-  // The value of the enum.
-  ReportingMode value;
-};
-
 struct VirtualSensorMetadata {
   bool available = true;
 
-  NullableDouble? maximum_frequency;
-  NullableDouble? minimum_frequency;
+  double? maximum_frequency;
+  double? minimum_frequency;
 
   // Only used by unit tests.
-  NullableReportingMode? reporting_mode;
+  ReportingMode? reporting_mode;
 };
 
 struct VirtualSensorInformation {
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index 93828ed..f109583 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -65,6 +65,7 @@
 #include "net/base/net_errors.h"
 #include "net/base/network_change_notifier.h"
 #include "net/base/network_isolation_key.h"
+#include "net/base/proxy_chain.h"
 #include "net/base/proxy_server.h"
 #include "net/base/proxy_string_util.h"
 #include "net/base/test_completion_callback.h"
@@ -5732,11 +5733,11 @@
             "Failed: FindProxyForURL(url=http://server.bad.dns/)");
 }
 
-// Test ensures that ProxyServer data is populated correctly across Mojo calls.
+// Test ensures that ProxyChain data is populated correctly across Mojo calls.
 // Basically it performs a set of URLLoader network requests, whose requests
-// configure proxies. Then it checks whether the expected proxy scheme is
-// respected.
-TEST_F(NetworkContextTest, EnsureProperProxyServerIsUsed) {
+// configure proxies. Then it checks whether the expected proxy chain is
+// propagated.
+TEST_F(NetworkContextTest, EnsureProperProxyChainIsUsed) {
   net::test_server::EmbeddedTestServer test_server;
   test_server.AddDefaultHandlers(
       base::FilePath(FILE_PATH_LITERAL("services/test/data")));
@@ -5763,6 +5764,9 @@
   proxy_config_set[1].expected_proxy_config_scheme =
       net::ProxyServer::SCHEME_DIRECT;
 
+  // TODO(https://crbug.com/1491092): Add a test case for a proxy chain with
+  // more than one hop.
+
   for (const auto& proxy_data : proxy_config_set) {
     mojom::NetworkContextParamsPtr context_params =
         CreateNetworkContextParamsForTesting();
@@ -5787,15 +5791,28 @@
     mojo::PendingRemote<mojom::URLLoader> loader;
     TestURLLoaderClient client;
     loader_factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
-        0 /* options */, request, client.CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), /*request_id=*/0,
+        /*options=*/0, request, client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     client.RunUntilComplete();
 
     EXPECT_TRUE(client.has_received_completion());
-    EXPECT_EQ(client.response_head()->proxy_server.scheme(),
-              proxy_data.expected_proxy_config_scheme);
+
+    ASSERT_TRUE(client.response_head()->proxy_chain.IsValid());
+    if (proxy_data.expected_proxy_config_scheme ==
+        net::ProxyServer::SCHEME_DIRECT) {
+      EXPECT_TRUE(client.response_head()->proxy_chain.is_direct());
+    } else {
+      const auto& proxy_chain = client.response_head()->proxy_chain;
+      for (size_t proxy_index = 0; proxy_index < proxy_chain.length();
+           ++proxy_index) {
+        // For simplicity the test assumes each proxy in the list has the same
+        // scheme, although this isn't necessarily the case.
+        EXPECT_EQ(proxy_chain.GetProxyServer(proxy_index).scheme(),
+                  proxy_data.expected_proxy_config_scheme);
+      }
+    }
   }
 }
 
@@ -6315,8 +6332,9 @@
 
   // |invalid_server| has no handlers set up so would return an empty response.
   EXPECT_EQ(response, "Echo");
-  EXPECT_EQ(client->response_head()->proxy_server,
-            ConvertToProxyServer(proxy_test_server));
+  EXPECT_EQ(
+      client->response_head()->proxy_chain.GetProxyServer(/*chain_index=*/0),
+      ConvertToProxyServer(proxy_test_server));
 }
 
 TEST_F(NetworkContextTest, MaximumCount) {
diff --git a/services/network/public/mojom/url_response_head.mojom b/services/network/public/mojom/url_response_head.mojom
index a58666f..105e0bc 100644
--- a/services/network/public/mojom/url_response_head.mojom
+++ b/services/network/public/mojom/url_response_head.mojom
@@ -120,8 +120,8 @@
   // prefetched URL.
   NavigationDeliveryType navigation_delivery_type = kDefault;
 
-  // The proxy server used for this request, if any.
-  ProxyServer proxy_server;
+  // The proxy chain used for this request, if any.
+  ProxyChain proxy_chain;
 
   // True if a service worker responded to the request. If the service worker
   // received a fetch event and did not call respondWith(), or was bypassed due
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index db1b5a2f..1e9ee248 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -40,6 +40,7 @@
 #include "net/base/load_flags.h"
 #include "net/base/load_timing_info.h"
 #include "net/base/mime_sniffer.h"
+#include "net/base/proxy_chain.h"
 #include "net/base/schemeful_site.h"
 #include "net/base/transport_info.h"
 #include "net/base/upload_bytes_element_reader.h"
@@ -1281,7 +1282,7 @@
   response->was_fetched_via_cache = url_request_->was_cached();
   response->is_validated = (response_info.cache_entry_status ==
                             net::HttpResponseInfo::ENTRY_VALIDATED);
-  response->proxy_server = url_request_->proxy_chain().proxy_server();
+  response->proxy_chain = url_request_->proxy_chain();
   response->network_accessed = response_info.network_accessed;
   response->async_revalidation_requested =
       response_info.async_revalidation_requested;
diff --git a/services/on_device_model/on_device_model_service.cc b/services/on_device_model/on_device_model_service.cc
index 3c6ff5ad..1e22a66 100644
--- a/services/on_device_model/on_device_model_service.cc
+++ b/services/on_device_model/on_device_model_service.cc
@@ -67,19 +67,20 @@
 
 OnDeviceModelService::~OnDeviceModelService() = default;
 
-void OnDeviceModelService::LoadModel(ModelAssets assets,
-                                     LoadModelCallback callback) {
-  auto model = CreateModel(std::move(assets));
-  if (!model) {
-    std::move(callback).Run(
-        mojom::LoadModelResult::NewError("Failed to create model."));
+void OnDeviceModelService::LoadModel(
+    ModelAssets assets,
+    mojo::PendingReceiver<mojom::OnDeviceModel> model,
+    LoadModelCallback callback) {
+  auto model_impl = CreateModel(std::move(assets));
+  if (!model_impl) {
+    std::move(callback).Run("Failed to create model.");
     return;
   }
 
   mojo::PendingRemote<mojom::OnDeviceModel> remote;
-  model_receivers_.Add(std::make_unique<ModelWrapper>(std::move(model)),
-                       remote.InitWithNewPipeAndPassReceiver());
-  std::move(callback).Run(mojom::LoadModelResult::NewModel(std::move(remote)));
+  model_receivers_.Add(std::make_unique<ModelWrapper>(std::move(model_impl)),
+                       std::move(model));
+  std::move(callback).Run(std::nullopt);
 }
 
 void OnDeviceModelService::GetEstimatedPerformanceClass(
diff --git a/services/on_device_model/on_device_model_service.h b/services/on_device_model/on_device_model_service.h
index 633bc60..64d19a7e 100644
--- a/services/on_device_model/on_device_model_service.h
+++ b/services/on_device_model/on_device_model_service.h
@@ -31,7 +31,9 @@
   OnDeviceModelService& operator=(const OnDeviceModelService&) = delete;
 
   // mojom::OnDeviceModelService:
-  void LoadModel(ModelAssets assets, LoadModelCallback callback) override;
+  void LoadModel(ModelAssets assets,
+                 mojo::PendingReceiver<mojom::OnDeviceModel> model,
+                 LoadModelCallback callback) override;
   void GetEstimatedPerformanceClass(
       GetEstimatedPerformanceClassCallback callback) override;
 
diff --git a/services/on_device_model/on_device_model_service_unittest.cc b/services/on_device_model/on_device_model_service_unittest.cc
index 50024c0..97a953b 100644
--- a/services/on_device_model/on_device_model_service_unittest.cc
+++ b/services/on_device_model/on_device_model_service_unittest.cc
@@ -49,12 +49,12 @@
   mojo::Remote<mojom::OnDeviceModel> LoadModel() {
     base::RunLoop run_loop;
     mojo::Remote<mojom::OnDeviceModel> remote;
-    service()->LoadModel(
-        ModelAssets(),
-        base::BindLambdaForTesting([&](mojom::LoadModelResultPtr result) {
-          remote.Bind(std::move(result->get_model()));
-          run_loop.Quit();
-        }));
+    service()->LoadModel(ModelAssets(), remote.BindNewPipeAndPassReceiver(),
+                         base::BindLambdaForTesting(
+                             [&](const std::optional<std::string>& error) {
+                               EXPECT_FALSE(error.has_value());
+                               run_loop.Quit();
+                             }));
     run_loop.Run();
     return remote;
   }
diff --git a/services/on_device_model/public/mojom/on_device_model.mojom b/services/on_device_model/public/mojom/on_device_model.mojom
index 0a200dc..32478b48 100644
--- a/services/on_device_model/public/mojom/on_device_model.mojom
+++ b/services/on_device_model/public/mojom/on_device_model.mojom
@@ -37,7 +37,7 @@
 
   // Executes model on the given input. The input will be added on top of the
   // context provided by |AddContext()|. The response will be streamed to
-  // |response|.
+  // |response|. To cancel the request, close the |response| pipe.
   Execute(InputOptions input, pending_remote<StreamingResponder> response);
 };
 
@@ -56,18 +56,8 @@
   mojo_base.mojom.File? weights;
 };
 
-// The result of OnDeviceModelService.LoadModel().
-union LoadModelResult {
-  // On successful load, this field is populated with a Remote to control the
-  // loaded model.
-  pending_remote<OnDeviceModel> model;
-
-  // On load failure, this field is populated with a description of the failure.
-  string error;
-};
-
 // Classifies the device based on how fast it is estimated to be able to run a
-// model..
+// model.
 enum PerformanceClass {
   // There was an error running the benchmark. The device is likely not able to
   // run any models.
@@ -86,8 +76,10 @@
 [ServiceSandbox=sandbox.mojom.Sandbox.kOnDeviceModelExecution,
  RequireContext=sandbox.mojom.Context.kBrowser]
 interface OnDeviceModelService {
-  // Initializes a new model instance given `assets`.
-  LoadModel(ModelAssets assets) => (LoadModelResult result);
+  // Initializes a new model instance given `assets`. If an error is returned,
+  // the model pipe will be reset.
+  LoadModel(ModelAssets assets, pending_receiver<OnDeviceModel> model) =>
+      (string? error);
 
   // Returns the performance class based on benchmarks run on the device.
   GetEstimatedPerformanceClass() => (PerformanceClass performance_class);
diff --git a/services/tracing/public/cpp/BUILD.gn b/services/tracing/public/cpp/BUILD.gn
index 7a86f9d..41ba1d1 100644
--- a/services/tracing/public/cpp/BUILD.gn
+++ b/services/tracing/public/cpp/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/compiler/compiler.gni")
 import("//build/config/features.gni")
 import("//build_overrides/build.gni")
diff --git a/testing/buildbot/autoshard_exceptions.json b/testing/buildbot/autoshard_exceptions.json
index ce79ac50..a8792d9 100644
--- a/testing/buildbot/autoshard_exceptions.json
+++ b/testing/buildbot/autoshard_exceptions.json
@@ -94,6 +94,23 @@
                 "shards": "16"
             }
         },
+        "chromeos-amd64-generic-rel-renamed": {
+            "chrome_all_tast_tests": {
+                "debug": {
+                    "avg_num_builds_per_peak_hour": 96,
+                    "estimated_bot_hour_delta": 56.32,
+                    "prev_avg_pending_time_sec": 205.5,
+                    "prev_p50_pending_time_sec": 4.0,
+                    "prev_p90_pending_time_sec": 755.0,
+                    "prev_percentile_duration_minutes": 22.35,
+                    "prev_shard_count": 7,
+                    "simulated_max_shard_duration": 12.03,
+                    "test_overhead_min": 5.866666666666666,
+                    "try_builder": "chromeos-amd64-generic-rel-renamed"
+                },
+                "shards": 13
+            }
+        },
         "linux-chromeos-rel": {
             "ash_pixeltests": {
                 "debug": {
@@ -479,45 +496,48 @@
             },
             "content_browsertests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "73.0",
-                    "estimated_bot_hour_delta": "-2.27",
-                    "prev_avg_pending_time_sec": "449.3",
-                    "prev_p50_pending_time_sec": "76.0",
-                    "prev_p90_pending_time_sec": "1455.0",
-                    "prev_percentile_duration_minutes": "14.38",
-                    "prev_shard_count": "43",
-                    "simulated_max_shard_duration": "14.72",
+                    "avg_num_builds_per_peak_hour": 103,
+                    "estimated_bot_hour_delta": 21.63,
+                    "prev_avg_pending_time_sec": 445.8,
+                    "prev_p50_pending_time_sec": 82.0,
+                    "prev_p90_pending_time_sec": 1465.0,
+                    "prev_percentile_duration_minutes": 21.88,
+                    "prev_shard_count": 42,
+                    "simulated_max_shard_duration": 14.59,
+                    "test_overhead_min": 0.6,
                     "try_builder": "linux_chromium_tsan_rel_ng"
                 },
-                "shards": "42"
+                "shards": 63
             },
             "interactive_ui_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "82.0",
-                    "estimated_bot_hour_delta": "2.8",
-                    "prev_avg_pending_time_sec": "101.2",
-                    "prev_p50_pending_time_sec": "5.0",
-                    "prev_p90_pending_time_sec": "318.0",
-                    "prev_percentile_duration_minutes": "15.29",
-                    "prev_shard_count": "40",
-                    "simulated_max_shard_duration": "14.92",
+                    "avg_num_builds_per_peak_hour": 103,
+                    "estimated_bot_hour_delta": 9.61,
+                    "prev_avg_pending_time_sec": 449.5,
+                    "prev_p50_pending_time_sec": 82.0,
+                    "prev_p90_pending_time_sec": 1467.0,
+                    "prev_percentile_duration_minutes": 17.76,
+                    "prev_shard_count": 41,
+                    "simulated_max_shard_duration": 14.86,
+                    "test_overhead_min": 0.7,
                     "try_builder": "linux_chromium_tsan_rel_ng"
                 },
-                "shards": "41"
+                "shards": 49
             },
             "sync_integration_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "76.0",
-                    "estimated_bot_hour_delta": "-2.22",
-                    "prev_avg_pending_time_sec": "392.1",
-                    "prev_p50_pending_time_sec": "75.0",
-                    "prev_p90_pending_time_sec": "1472.0",
-                    "prev_percentile_duration_minutes": "12.93",
-                    "prev_shard_count": "7",
-                    "simulated_max_shard_duration": "15.08",
+                    "avg_num_builds_per_peak_hour": 103,
+                    "estimated_bot_hour_delta": 1.09,
+                    "prev_avg_pending_time_sec": 438.5,
+                    "prev_p50_pending_time_sec": 66.0,
+                    "prev_p90_pending_time_sec": 1455.0,
+                    "prev_percentile_duration_minutes": 17.27,
+                    "prev_shard_count": 6,
+                    "simulated_max_shard_duration": 14.8,
+                    "test_overhead_min": 0.6333333333333333,
                     "try_builder": "linux_chromium_tsan_rel_ng"
                 },
-                "shards": "6"
+                "shards": 7
             },
             "unit_tests": {
                 "debug": {
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 60ea20a..cc16ed8 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1705,6 +1705,7 @@
         "cros_board": "brya",
         "cros_img": "brya-release/R118-15604.42.0",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests BRYA_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -1723,6 +1724,7 @@
         "cros_board": "brya",
         "cros_img": "brya-release/R119-15633.10.0",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests BRYA_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -1759,6 +1761,7 @@
         "cros_board": "brya",
         "cros_img": "brya-release/R117-15572.63.2",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests BRYA_RELEASE_STABLE",
         "resultdb": {
           "enable": true,
@@ -1776,6 +1779,7 @@
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "dedede",
         "cros_img": "dedede-release/R118-15604.42.0",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests DEDEDE_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -1793,6 +1797,7 @@
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "dedede",
         "cros_img": "dedede-release/R119-15633.10.0",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests DEDEDE_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -1827,6 +1832,7 @@
         "autotest_name": "tast.lacros-from-gcs",
         "cros_board": "dedede",
         "cros_img": "dedede-release/R117-15572.63.0",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests DEDEDE_RELEASE_STABLE",
         "resultdb": {
           "enable": true,
@@ -1845,6 +1851,7 @@
         "cros_board": "fizz",
         "cros_img": "fizz-release/R118-15604.42.0",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests FIZZ_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -1863,6 +1870,7 @@
         "cros_board": "fizz",
         "cros_img": "fizz-release/R119-15633.10.0",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests FIZZ_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -1899,6 +1907,7 @@
         "cros_board": "fizz",
         "cros_img": "fizz-release/R117-15572.63.0",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests FIZZ_RELEASE_STABLE",
         "resultdb": {
           "enable": true,
@@ -1917,6 +1926,7 @@
         "cros_board": "guybrush",
         "cros_img": "guybrush-release/R118-15604.42.0",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests GUYBRUSH_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -1935,6 +1945,7 @@
         "cros_board": "guybrush",
         "cros_img": "guybrush-release/R119-15626.0.0",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests GUYBRUSH_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -1971,6 +1982,7 @@
         "cros_board": "guybrush",
         "cros_img": "guybrush-release/R117-15572.63.0",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests GUYBRUSH_RELEASE_STABLE",
         "resultdb": {
           "enable": true,
@@ -1989,6 +2001,7 @@
         "cros_board": "puff",
         "cros_img": "puff-release/R118-15604.42.0",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests PUFF_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -2007,6 +2020,7 @@
         "cros_board": "puff",
         "cros_img": "puff-release/R119-15633.10.0",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests PUFF_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -2043,6 +2057,7 @@
         "cros_board": "puff",
         "cros_img": "puff-release/R117-15572.63.0",
         "dut_pool": "chrome",
+        "experiment_percentage": 100,
         "name": "lacros_all_tast_tests PUFF_RELEASE_STABLE",
         "resultdb": {
           "enable": true,
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 6d40f4ce..1ee35a1 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -1145,7 +1145,7 @@
             }
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 7
+          "shards": 13
         },
         "test": "chrome_all_tast_tests",
         "test_id_prefix": "ninja://chromeos:chrome_all_tast_tests/"
@@ -6096,9 +6096,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_v121.0.6110.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6110.0",
+        "description": "Run with ash-chrome version 121.0.6111.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6108,8 +6108,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6110.0",
-              "revision": "version:121.0.6110.0"
+              "location": "lacros_version_skew_tests_v121.0.6111.0",
+              "revision": "version:121.0.6111.0"
             }
           ],
           "dimensions": {
@@ -6125,9 +6125,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_v120.0.6085.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 120.0.6085.0",
+        "description": "Run with ash-chrome version 120.0.6099.8",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6137,8 +6137,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v120.0.6085.0",
-              "revision": "version:120.0.6085.0"
+              "location": "lacros_version_skew_tests_v120.0.6099.8",
+              "revision": "version:120.0.6099.8"
             }
           ],
           "dimensions": {
@@ -6246,9 +6246,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6110.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6110.0",
+        "description": "Run with ash-chrome version 121.0.6111.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6258,8 +6258,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6110.0",
-              "revision": "version:121.0.6110.0"
+              "location": "lacros_version_skew_tests_v121.0.6111.0",
+              "revision": "version:121.0.6111.0"
             }
           ],
           "dimensions": {
@@ -6275,9 +6275,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6085.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 120.0.6085.0",
+        "description": "Run with ash-chrome version 120.0.6099.8",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6287,8 +6287,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v120.0.6085.0",
-              "revision": "version:120.0.6085.0"
+              "location": "lacros_version_skew_tests_v120.0.6099.8",
+              "revision": "version:120.0.6099.8"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index babcb42..71e1edb 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -20451,9 +20451,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_v121.0.6110.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6110.0",
+        "description": "Run with ash-chrome version 121.0.6111.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20463,8 +20463,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6110.0",
-              "revision": "version:121.0.6110.0"
+              "location": "lacros_version_skew_tests_v121.0.6111.0",
+              "revision": "version:121.0.6111.0"
             }
           ],
           "dimensions": {
@@ -20480,9 +20480,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_v120.0.6085.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 120.0.6085.0",
+        "description": "Run with ash-chrome version 120.0.6099.8",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20492,8 +20492,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v120.0.6085.0",
-              "revision": "version:120.0.6085.0"
+              "location": "lacros_version_skew_tests_v120.0.6099.8",
+              "revision": "version:120.0.6099.8"
             }
           ],
           "dimensions": {
@@ -20601,9 +20601,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6110.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6110.0",
+        "description": "Run with ash-chrome version 121.0.6111.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20613,8 +20613,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6110.0",
-              "revision": "version:121.0.6110.0"
+              "location": "lacros_version_skew_tests_v121.0.6111.0",
+              "revision": "version:121.0.6111.0"
             }
           ],
           "dimensions": {
@@ -20630,9 +20630,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6085.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 120.0.6085.0",
+        "description": "Run with ash-chrome version 120.0.6099.8",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20642,8 +20642,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v120.0.6085.0",
-              "revision": "version:120.0.6085.0"
+              "location": "lacros_version_skew_tests_v120.0.6099.8",
+              "revision": "version:120.0.6099.8"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 3de24bc..9980210 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -43401,9 +43401,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_v121.0.6110.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6110.0",
+        "description": "Run with ash-chrome version 121.0.6111.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43412,8 +43412,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6110.0",
-              "revision": "version:121.0.6110.0"
+              "location": "lacros_version_skew_tests_v121.0.6111.0",
+              "revision": "version:121.0.6111.0"
             }
           ],
           "dimensions": {
@@ -43430,9 +43430,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_v120.0.6085.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 120.0.6085.0",
+        "description": "Run with ash-chrome version 120.0.6099.8",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43441,8 +43441,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v120.0.6085.0",
-              "revision": "version:120.0.6085.0"
+              "location": "lacros_version_skew_tests_v120.0.6099.8",
+              "revision": "version:120.0.6099.8"
             }
           ],
           "dimensions": {
@@ -43551,9 +43551,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6110.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6110.0",
+        "description": "Run with ash-chrome version 121.0.6111.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43562,8 +43562,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6110.0",
-              "revision": "version:121.0.6110.0"
+              "location": "lacros_version_skew_tests_v121.0.6111.0",
+              "revision": "version:121.0.6111.0"
             }
           ],
           "dimensions": {
@@ -43580,9 +43580,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6085.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 120.0.6085.0",
+        "description": "Run with ash-chrome version 120.0.6099.8",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43591,8 +43591,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v120.0.6085.0",
-              "revision": "version:120.0.6085.0"
+              "location": "lacros_version_skew_tests_v120.0.6099.8",
+              "revision": "version:120.0.6099.8"
             }
           ],
           "dimensions": {
@@ -44860,9 +44860,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_v121.0.6110.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6110.0",
+        "description": "Run with ash-chrome version 121.0.6111.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -44871,8 +44871,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6110.0",
-              "revision": "version:121.0.6110.0"
+              "location": "lacros_version_skew_tests_v121.0.6111.0",
+              "revision": "version:121.0.6111.0"
             }
           ],
           "dimensions": {
@@ -44889,9 +44889,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_v120.0.6085.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 120.0.6085.0",
+        "description": "Run with ash-chrome version 120.0.6099.8",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -44900,8 +44900,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v120.0.6085.0",
-              "revision": "version:120.0.6085.0"
+              "location": "lacros_version_skew_tests_v120.0.6099.8",
+              "revision": "version:120.0.6099.8"
             }
           ],
           "dimensions": {
@@ -45010,9 +45010,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6110.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6110.0",
+        "description": "Run with ash-chrome version 121.0.6111.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45021,8 +45021,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6110.0",
-              "revision": "version:121.0.6110.0"
+              "location": "lacros_version_skew_tests_v121.0.6111.0",
+              "revision": "version:121.0.6111.0"
             }
           ],
           "dimensions": {
@@ -45039,9 +45039,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6085.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 120.0.6085.0",
+        "description": "Run with ash-chrome version 120.0.6099.8",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45050,8 +45050,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v120.0.6085.0",
-              "revision": "version:120.0.6085.0"
+              "location": "lacros_version_skew_tests_v120.0.6099.8",
+              "revision": "version:120.0.6099.8"
             }
           ],
           "dimensions": {
@@ -45705,9 +45705,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_v121.0.6110.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6110.0",
+        "description": "Run with ash-chrome version 121.0.6111.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45716,8 +45716,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6110.0",
-              "revision": "version:121.0.6110.0"
+              "location": "lacros_version_skew_tests_v121.0.6111.0",
+              "revision": "version:121.0.6111.0"
             }
           ],
           "dimensions": {
@@ -45733,9 +45733,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_v120.0.6085.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 120.0.6085.0",
+        "description": "Run with ash-chrome version 120.0.6099.8",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45744,8 +45744,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v120.0.6085.0",
-              "revision": "version:120.0.6085.0"
+              "location": "lacros_version_skew_tests_v120.0.6099.8",
+              "revision": "version:120.0.6099.8"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index fe302bcb..8cb24f1 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -7933,7 +7933,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 42
+          "shards": 63
         },
         "test": "content_browsertests",
         "test_id_prefix": "ninja://content/test:content_browsertests/"
@@ -8334,7 +8334,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 41
+          "shards": 49
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
@@ -8798,7 +8798,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 6
+          "shards": 7
         },
         "test": "sync_integration_tests",
         "test_id_prefix": "ninja://chrome/test:sync_integration_tests/"
@@ -16249,12 +16249,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_v121.0.6110.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 121.0.6110.0",
+        "description": "Run with ash-chrome version 121.0.6111.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16264,8 +16264,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6110.0",
-              "revision": "version:121.0.6110.0"
+              "location": "lacros_version_skew_tests_v121.0.6111.0",
+              "revision": "version:121.0.6111.0"
             }
           ],
           "dimensions": {
@@ -16281,12 +16281,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_v120.0.6085.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 120.0.6085.0",
+        "description": "Run with ash-chrome version 120.0.6099.8",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16296,8 +16296,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v120.0.6085.0",
-              "revision": "version:120.0.6085.0"
+              "location": "lacros_version_skew_tests_v120.0.6099.8",
+              "revision": "version:120.0.6099.8"
             }
           ],
           "dimensions": {
@@ -16419,12 +16419,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6110.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 121.0.6110.0",
+        "description": "Run with ash-chrome version 121.0.6111.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16434,8 +16434,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6110.0",
-              "revision": "version:121.0.6110.0"
+              "location": "lacros_version_skew_tests_v121.0.6111.0",
+              "revision": "version:121.0.6111.0"
             }
           ],
           "dimensions": {
@@ -16451,12 +16451,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6085.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 120.0.6085.0",
+        "description": "Run with ash-chrome version 120.0.6099.8",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16466,8 +16466,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v120.0.6085.0",
-              "revision": "version:120.0.6085.0"
+              "location": "lacros_version_skew_tests_v120.0.6099.8",
+              "revision": "version:120.0.6099.8"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 81c575e..c8777e7 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -900,7 +900,7 @@
       },
       'mac10.15-blink-rel': {
         'swarming': {
-          'shards': 12,
+          'shards': 1,
           'hard_timeout': 2400,
         },
       },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index de56ff73..f0f25e3 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -4102,6 +4102,19 @@
       },
     },
 
+    'lacros_skylab_tests_version_skew': {
+      'lacros_all_tast_tests': {
+        'tast_expr': '("group:mainline" && ("dep:lacros_stable" || "dep:lacros") && !informational)',
+        'test_level_retries': 2,
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'timeout_sec': 10800,
+        'shards': 2,
+        'experiment_percentage': 100,
+      },
+    },
+
     'lacros_skylab_tests_with_gtests': {
       'chromeos_integration_tests': {},
     },
@@ -7494,30 +7507,34 @@
     },
 
     'lacros_skylab_tests_amd64_generic': {
-      'lacros_skylab_tests': {
+      'lacros_skylab_tests_version_skew': {
         'variants': [
-          'CROS_BRYA_RELEASE_LKGM',
           'CROS_BRYA_RELEASE_DEV',
           'CROS_BRYA_RELEASE_BETA',
           'CROS_BRYA_RELEASE_STABLE',
-          'CROS_DEDEDE_RELEASE_LKGM',
           'CROS_DEDEDE_RELEASE_DEV',
           'CROS_DEDEDE_RELEASE_BETA',
           'CROS_DEDEDE_RELEASE_STABLE',
-          'CROS_FIZZ_RELEASE_LKGM',
           'CROS_FIZZ_RELEASE_DEV',
           'CROS_FIZZ_RELEASE_BETA',
           'CROS_FIZZ_RELEASE_STABLE',
-          'CROS_GUYBRUSH_RELEASE_LKGM',
           'CROS_GUYBRUSH_RELEASE_DEV',
           'CROS_GUYBRUSH_RELEASE_BETA',
           'CROS_GUYBRUSH_RELEASE_STABLE',
-          'CROS_PUFF_RELEASE_LKGM',
           'CROS_PUFF_RELEASE_DEV',
           'CROS_PUFF_RELEASE_BETA',
           'CROS_PUFF_RELEASE_STABLE',
         ],
       },
+      'lacros_skylab_tests': {
+        'variants': [
+          'CROS_BRYA_RELEASE_LKGM',
+          'CROS_DEDEDE_RELEASE_LKGM',
+          'CROS_FIZZ_RELEASE_LKGM',
+          'CROS_GUYBRUSH_RELEASE_LKGM',
+          'CROS_PUFF_RELEASE_LKGM',
+        ],
+      },
       'lacros_skylab_tests_with_gtests': {
         'variants': [
           'CROS_BRYA_RELEASE_LKGM',
diff --git a/testing/buildbot/tryserver.blink.json b/testing/buildbot/tryserver.blink.json
index 7e0cfa1..72931f5 100644
--- a/testing/buildbot/tryserver.blink.json
+++ b/testing/buildbot/tryserver.blink.json
@@ -285,8 +285,7 @@
             "os": "Mac-10.15"
           },
           "hard_timeout": 2400,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 12
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "blink_wpt_tests",
         "test_id_prefix": "ninja://:blink_wpt_tests/"
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index ce69e6ec4..f47dcc27 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -70,32 +70,32 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 121.0.6110.0',
+    'description': 'Run with ash-chrome version 121.0.6111.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6110.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6111.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v121.0.6110.0',
-          'revision': 'version:121.0.6110.0',
+          'location': 'lacros_version_skew_tests_v121.0.6111.0',
+          'revision': 'version:121.0.6111.0',
         },
       ],
     },
   },
   'LACROS_VERSION_SKEW_DEV': {
     'identifier': 'Lacros version skew testing ash dev',
-    'description': 'Run with ash-chrome version 120.0.6085.0',
+    'description': 'Run with ash-chrome version 120.0.6099.8',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6085.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v120.0.6099.8/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v120.0.6085.0',
-          'revision': 'version:120.0.6085.0',
+          'location': 'lacros_version_skew_tests_v120.0.6099.8',
+          'revision': 'version:120.0.6099.8',
         },
       ],
     },
diff --git a/testing/test.gni b/testing/test.gni
index ec22fd7..d181389 100644
--- a/testing/test.gni
+++ b/testing/test.gni
@@ -39,7 +39,7 @@
   import("//build/config/android/rules.gni")
   import("//build/config/sanitizers/sanitizers.gni")
 } else if (is_fuchsia) {
-  import("//build/config/chromecast_build.gni")
+  import("//build/config/cast.gni")
   import("//build/config/fuchsia/generate_runner_scripts.gni")
   import("//third_party/fuchsia-gn-sdk/src/cmc.gni")
   import("//third_party/fuchsia-gn-sdk/src/component.gni")
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index a3bddeb..9d172aef 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2598,6 +2598,29 @@
             ]
         }
     ],
+    "BrowsingTopicsParameters": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "chromeos_lacros",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "PrioritizeHighUtilityTopics",
+                    "params": {
+                        "prioritized_topics_list": "57,86,126,149,172,180,196,207,239,254,263,272,289,299,332"
+                    },
+                    "enable_features": [
+                        "BrowsingTopicsParameters"
+                    ]
+                }
+            ]
+        }
+    ],
     "BubbleMetricsApi": [
         {
             "platforms": [
@@ -2640,6 +2663,21 @@
             ]
         }
     ],
+    "CCTPageInsightsHub": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "CCTPageInsightsHub"
+                    ]
+                }
+            ]
+        }
+    ],
     "CCTRealTimeEngagementSignalsAlternativeImpl": [
         {
             "platforms": [
@@ -8512,6 +8550,30 @@
             ]
         }
     ],
+    "IOSHideFeedWithSearchChoice": [
+        {
+            "platforms": [
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "IOSHideFeedWithSearchChoice"
+                    ]
+                },
+                {
+                    "name": "Enabled with targeting",
+                    "params": {
+                        "IOSHideFeedWithSearchChoiceTargeted": "true"
+                    },
+                    "enable_features": [
+                        "IOSHideFeedWithSearchChoice"
+                    ]
+                }
+            ]
+        }
+    ],
     "IOSIPHForSafariSwitcher": [
         {
             "platforms": [
@@ -11724,6 +11786,22 @@
             ]
         }
     ],
+    "OsFeedbackDialog": [
+        {
+            "platforms": [
+                "chromeos",
+                "chromeos_lacros"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "OsFeedbackDialog"
+                    ]
+                }
+            ]
+        }
+    ],
     "OutOfProcessPrintDriversPrint": [
         {
             "platforms": [
diff --git a/third_party/android_sdk/BUILD.gn b/third_party/android_sdk/BUILD.gn
index 14af04e..970675e 100644
--- a/third_party/android_sdk/BUILD.gn
+++ b/third_party/android_sdk/BUILD.gn
@@ -13,11 +13,6 @@
     jar_path = android_sdk_jar
   }
 
-  android_system_java_prebuilt("android_privacy_sandbox_sdk_java") {
-    jar_path = "public/platforms/android-TiramisuPrivacySandbox/android.jar"
-    output_name = "android.privacy-sandbox.jar"
-  }
-
   template("android_sdk_optional_library") {
     forward_variables_from(invoker, [ "testonly" ])
     _manifest_path = "$target_gen_dir/$target_name/AndroidManifest.xml"
diff --git a/third_party/androidx/customizations.gni b/third_party/androidx/customizations.gni
index b3069dc8..5b383f1 100644
--- a/third_party/androidx/customizations.gni
+++ b/third_party/androidx/customizations.gni
@@ -65,11 +65,10 @@
       ignore_proguard_configs = true
     } else if (target_name ==
                "androidx_privacysandbox_ads_ads_adservices_java") {
-      alternative_android_sdk_dep =
-          "//third_party/android_sdk:android_privacy_sandbox_sdk_java"
-
-      # https://crbug.com/1448095
-      mergeable_android_manifests = [ "0_privacysandbox_AndroidManifest.xml" ]
+      if (!is_high_end_android) {
+        # https://crbug.com/1448095
+        mergeable_android_manifests = [ "0_privacysandbox_AndroidManifest.xml" ]
+      }
     } else if (target_name == "androidx_startup_startup_runtime_java") {
       # Keeps emoji2 code. See http://crbug.com/1205141
       ignore_proguard_configs = true
diff --git a/third_party/angle b/third_party/angle
index eebf069..32f209b 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit eebf069c1d98952c9cde6f4e5f81383736b10163
+Subproject commit 32f209b83f782d396d9197744b897af421762726
diff --git a/third_party/blink/public/common/fenced_frame/fenced_frame_utils.h b/third_party/blink/public/common/fenced_frame/fenced_frame_utils.h
index e389aba33..d3212db3 100644
--- a/third_party/blink/public/common/fenced_frame/fenced_frame_utils.h
+++ b/third_party/blink/public/common/fenced_frame/fenced_frame_utils.h
@@ -43,6 +43,9 @@
 inline constexpr char kAutomaticBeaconOutcomeHistogram[] =
     "Navigation.AutomaticBeaconOutcome";
 
+inline constexpr char kAutomaticBeaconEventTypeHistogram[] =
+    "Navigation.FencedFrameAutomaticBeaconEventType";
+
 // Corresponds to the "FencedFrameCreationOutcome" histogram enumeration type in
 // tools/metrics/histograms/enums.xml.
 //
diff --git a/third_party/blink/public/mojom/fenced_frame/fenced_frame_config.mojom b/third_party/blink/public/mojom/fenced_frame/fenced_frame_config.mojom
index 5b765bc..858d9ae 100644
--- a/third_party/blink/public/mojom/fenced_frame/fenced_frame_config.mojom
+++ b/third_party/blink/public/mojom/fenced_frame/fenced_frame_config.mojom
@@ -47,10 +47,12 @@
 // setReportEventDataForAutomaticBeacons(), they are converted into an enum
 // and used as the key in the automatic beacon info mapping stored in the
 // browser.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum AutomaticBeaconType {
-  kDeprecatedTopNavigation,
-  kTopNavigationStart,
-  kTopNavigationCommit
+  kDeprecatedTopNavigation = 0,
+  kTopNavigationStart = 1,
+  kTopNavigationCommit = 2
 };
 
 union PotentiallyOpaqueURL {
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 ee2d89e5..143231e 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
@@ -3548,8 +3548,8 @@
   kOBSOLETE_GestureScrollEnd = 4222,
   kArrayBufferTooBigForWebAPI = 4223,
   kFedCmRevoke = 4224,
-  kFedCmLogout = 4225,
-  kFedCmLogoutRps = 4226,
+  kOBSOLETE_FedCmLogout = 4225,
+  kOBSOLETE_FedCmLogoutRps = 4226,
   kV8Navigator_DeprecatedReplaceInURN_Method = 4227,
   // The items above roughly this point are available in the M103 branch.
 
diff --git a/third_party/blink/public/mojom/webid/federated_auth_request.mojom b/third_party/blink/public/mojom/webid/federated_auth_request.mojom
index 422424ba..60afc6fb 100644
--- a/third_party/blink/public/mojom/webid/federated_auth_request.mojom
+++ b/third_party/blink/public/mojom/webid/federated_auth_request.mojom
@@ -33,12 +33,6 @@
   kError,
 };
 
-enum LogoutRpsStatus {
-  kSuccess,
-  kErrorTooManyRequests,
-  kError,
-};
-
 // Represents the fetch result from a IdentityProvider.revoke() request.
 // It is used to determine whether a JavaScript exception should be
 // thrown, and what the error message of such exception should say.
@@ -65,18 +59,6 @@
   kWidget
 };
 
-// The details of a single logout request from an identity provider.
-struct LogoutRpsRequest {
-  // URL to which the request will be sent. The origin is validated to
-  // have an associated active session.
-  url.mojom.Url url;
-
-  // Identifier for the account being logged out. This is used to verify that
-  // the logout request correlates to a previous sign-in event, and will
-  // result in the corresponding active session being terminated.
-  string account_id;
-};
-
 // The details of different mechanisms that allows the browser
 // to intermediate the exchange of the user's entities.
 // Currently, federated identities are supported, and digital credentials
@@ -221,10 +203,6 @@
   // actual token.
   ResolveTokenRequest(string token) => (bool success);
 
-  // Contact the list of Relying Party logout endpoints and account IDs to
-  // attempt to initiate user logout.
-  LogoutRps(array<LogoutRpsRequest> rp_logout_requests) => (LogoutRpsStatus status);
-
   // Marks the user as logged in/out to the IDP on this origin.
   SetIdpSigninStatus(url.mojom.Origin origin, IdpSigninStatus status);
 
diff --git a/third_party/blink/public/platform/web_content_settings_client.h b/third_party/blink/public/platform/web_content_settings_client.h
index 99f89fa..096cd6eb 100644
--- a/third_party/blink/public/platform/web_content_settings_client.h
+++ b/third_party/blink/public/platform/web_content_settings_client.h
@@ -11,6 +11,7 @@
 #include "base/functional/callback.h"
 #include "base/time/time.h"
 #include "third_party/blink/public/common/client_hints/enabled_client_hints.h"
+#include "third_party/blink/public/mojom/navigation/renderer_content_settings.mojom.h"
 
 namespace blink {
 
@@ -92,10 +93,6 @@
   // interface.
   virtual bool AllowMutationEvents(bool default_value) { return default_value; }
 
-  virtual bool AllowPopupsAndRedirects(bool default_value) {
-    return default_value;
-  }
-
   // Reports that passive mixed content was found at the provided URL.
   virtual void PassiveInsecureContentFound(const WebURL&) {}
 
@@ -103,6 +100,10 @@
   // were enabled.
   virtual void DidNotAllowScript() {}
 
+  // Notifies the client that the frame would have loaded an image if image were
+  // enabled.
+  virtual void DidNotAllowImage() {}
+
   // Called to persist the received client hint preferences when |url| was
   // fetched. The preferences should be persisted for |duration|.
   virtual void PersistClientHints(
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 2e6598b..c9367bd 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/compiler/compiler.gni")
 import("//build/config/dcheck_always_on.gni")
 import("//build/config/python.gni")
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 59da818..bbe63e15 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -594,6 +594,17 @@
 }
 
 bool Element::IsFocusableStyle() const {
+  // TODO(vmpstr): Note that this may be called by accessibility during layout
+  // tree attachment, at which point we might not have cleared all of the dirty
+  // bits to ensure that the layout tree doesn't need an update. This should be
+  // fixable by deferring AX tree updates as a separate phase after layout tree
+  // attachment has happened. At that point `InStyleRecalc()` portion of the
+  // following DCHECK can be removed.
+  DCHECK(
+      !GetDocument().IsActive() || GetDocument().InStyleRecalc() ||
+      !GetDocument().NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(*this))
+      << *this;
+
   if (LayoutObject* layout_object = GetLayoutObject()) {
     return layout_object->StyleRef().IsFocusable();
   }
@@ -6095,18 +6106,7 @@
          IsScrollableContainerThatShouldBeKeyboardFocusable();
 }
 
-bool Element::IsFocusableStyleNeverLayoutForAccessibilityOnly() const {
-  DCHECK(!NeedsStyleRecalc()) << this;
-  DocumentLifecycle::DisallowTransitionScope scope(GetDocument().Lifecycle());
-  return IsFocusableStyle();
-}
-
-bool Element::IsFocusable(
-    bool disallow_layout_updates_for_accessibility_only) const {
-  if (UNLIKELY(disallow_layout_updates_for_accessibility_only)) {
-    return isConnected() && IsFocusableStyleNeverLayoutForAccessibilityOnly() &&
-           SupportsFocus();
-  }
+bool Element::IsFocusable() const {
   return isConnected() && IsFocusableStyleAfterUpdate() && SupportsFocus();
 }
 
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index 5856991..86d06ed3 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -821,11 +821,7 @@
   // focusable (using the mouse). This method can be called when layout is not
   // clean, but the method might trigger a lifecycle update in that case. This
   // method will not trigger a lifecycle update if layout is already clean.
-  // If the |disallow_layout_updates_for_accessibility_only| argument is true,
-  // which should only be used by a11y code, layout updates will never be
-  // performed.
-  virtual bool IsFocusable(
-      bool disallow_layout_updates_for_accessibility_only = false) const;
+  virtual bool IsFocusable() const;
 
   // IsKeyboardFocusable is true for the subset of mouse focusable elements (for
   // which IsFocusable() is true) that are in the tab cycle. This method
@@ -1338,11 +1334,6 @@
   // Similar to IsFocusableStyle, except that it will ensure that any deferred
   // work to create layout objects is completed (e.g. in display-locked trees).
   bool IsFocusableStyleAfterUpdate() const;
-  // This method should only be used by a11y code. It performs roughly the same
-  // focusability check as IsFocusableStyle(), but will never trigger a layout
-  // update. In some cases (e.g. in the presence of display locked trees),
-  // stale layout information may be used.
-  bool IsFocusableStyleNeverLayoutForAccessibilityOnly() const;
 
   // Is the node descendant of this in something clickable/activatable, such
   // that we shouldn't handle events targeting it?
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index f9517395..2f558c4 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -456,13 +456,17 @@
     return false;
   }
 
-  WebContentSettingsClient* settings_client =
-      GetFrame()->GetContentSettingsClient();
-  bool script_enabled = GetFrame()->GetSettings()->GetScriptEnabled();
-  if (settings_client)
-    script_enabled = settings_client->AllowScript(script_enabled);
-  if (!script_enabled && reason == kAboutToExecuteScript && settings_client)
-    settings_client->DidNotAllowScript();
+  bool allow_script_renderer = GetFrame()->GetSettings()->GetScriptEnabled();
+  bool allow_script_content_setting =
+      GetFrame()->GetContentSettings()->allow_script;
+  bool script_enabled = allow_script_renderer && allow_script_content_setting;
+  if (!script_enabled && reason == kAboutToExecuteScript) {
+    WebContentSettingsClient* settings_client =
+        GetFrame()->GetContentSettingsClient();
+    if (settings_client) {
+      settings_client->DidNotAllowScript();
+    }
+  }
   return script_enabled;
 }
 
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index e7086a8f..827d2bf 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -2001,9 +2001,8 @@
       return true;
     }
 
-    if (auto* settings_client = Client()->GetContentSettingsClient()) {
-      if (settings_client->AllowPopupsAndRedirects(false /* default_value*/))
-        return true;
+    if (GetContentSettings()->allow_popup) {
+      return true;
     }
     PrintNavigationErrorMessage(
         target_frame,
@@ -3725,4 +3724,9 @@
   return security_origin->IsSameOriginWith(top_security_origin);
 }
 
+const mojom::RendererContentSettingsPtr& LocalFrame::GetContentSettings() {
+  DCHECK(!IsDetached());
+  return loader_.GetDocumentLoader()->GetContentSettings();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 85f8e32..9f6bf1ba 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -62,6 +62,7 @@
 #include "third_party/blink/public/mojom/link_to_text/link_to_text.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/loader/resource_cache.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/navigation/renderer_content_settings.mojom.h"
 #include "third_party/blink/public/mojom/navigation/renderer_eviction_reason.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/reporting/reporting.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/script/script_evaluation_params.mojom-blink-forward.h"
@@ -902,6 +903,10 @@
     return *v8_local_compile_hints_producer_;
   }
 
+  // Gets the content settings associated with the current navigation commit.
+  // Can only be called while the frame is not detached.
+  const mojom::RendererContentSettingsPtr& GetContentSettings();
+
  private:
   friend class FrameNavigationDisabler;
   // LocalFrameMojoHandler is a part of LocalFrame.
diff --git a/third_party/blink/renderer/core/html/forms/clear_button_element.h b/third_party/blink/renderer/core/html/forms/clear_button_element.h
index bc32f5f..7d9bc00b 100644
--- a/third_party/blink/renderer/core/html/forms/clear_button_element.h
+++ b/third_party/blink/renderer/core/html/forms/clear_button_element.h
@@ -49,7 +49,7 @@
 
  private:
   void DetachLayoutTree(bool performing_reattach) override;
-  bool IsFocusable(bool) const override { return false; }
+  bool IsFocusable() const override { return false; }
   void DefaultEventHandler(Event&) override;
   bool IsClearButtonElement() const override;
 
diff --git a/third_party/blink/renderer/core/html/forms/spin_button_element.h b/third_party/blink/renderer/core/html/forms/spin_button_element.h
index 5eb3d278..f53cce0 100644
--- a/third_party/blink/renderer/core/html/forms/spin_button_element.h
+++ b/third_party/blink/renderer/core/html/forms/spin_button_element.h
@@ -89,7 +89,7 @@
   void StopRepeatingTimer();
   void RepeatingTimerFired(TimerBase*);
   bool ShouldRespondToMouseEvents() const;
-  bool IsFocusable(bool) const override { return false; }
+  bool IsFocusable() const override { return false; }
   void CalculateUpDownStateByMouseLocation(Event&);
 
   Member<SpinButtonOwner> spin_button_owner_;
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc
index b47582a..7263b0d 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.cc
+++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -141,22 +141,13 @@
          HTMLElement::SupportsFocus();
 }
 
-bool HTMLAnchorElement::IsFocusable(
-    bool disallow_layout_updates_for_accessibility_only) const {
-  if (disallow_layout_updates_for_accessibility_only) {
-    if (!IsFocusableStyleNeverLayoutForAccessibilityOnly()) {
-      return false;
-    }
-  } else {
-    if (!IsFocusableStyleAfterUpdate()) {
-      return false;
-    }
-  }
-  if (IsLink()) {
+bool HTMLAnchorElement::IsFocusable() const {
+  if (!IsFocusableStyleAfterUpdate())
+    return false;
+  if (IsLink())
     return SupportsFocus();
-  }
-  return HTMLElement::IsFocusable(
-      disallow_layout_updates_for_accessibility_only);
+
+  return HTMLElement::IsFocusable();
 }
 
 bool HTMLAnchorElement::IsKeyboardFocusable() const {
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.h b/third_party/blink/renderer/core/html/html_anchor_element.h
index 4d0ce46..103fa2c 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.h
+++ b/third_party/blink/renderer/core/html/html_anchor_element.h
@@ -114,8 +114,7 @@
  private:
   void AttributeChanged(const AttributeModificationParams&) override;
   bool ShouldHaveFocusAppearance() const final;
-  bool IsFocusable(bool disallow_layout_updates_for_accessibility_only =
-                       false) const override;
+  bool IsFocusable() const override;
   bool IsKeyboardFocusable() const override;
   void DefaultEventHandler(Event&) final;
   bool HasActivationBehavior() const override;
diff --git a/third_party/blink/renderer/core/html/html_area_element.cc b/third_party/blink/renderer/core/html/html_area_element.cc
index a6cbcc04..f3dabed 100644
--- a/third_party/blink/renderer/core/html/html_area_element.cc
+++ b/third_party/blink/renderer/core/html/html_area_element.cc
@@ -189,11 +189,9 @@
   return Element::IsKeyboardFocusable();
 }
 
-bool HTMLAreaElement::IsFocusable(
-    bool disallow_layout_updates_for_accessibility_only) const {
+bool HTMLAreaElement::IsFocusable() const {
   // Explicitly skip over the HTMLAnchorElement's mouse focus behavior.
-  return HTMLElement::IsFocusable(
-      disallow_layout_updates_for_accessibility_only);
+  return HTMLElement::IsFocusable();
 }
 
 bool HTMLAreaElement::IsFocusableStyle() const {
diff --git a/third_party/blink/renderer/core/html/html_area_element.h b/third_party/blink/renderer/core/html/html_area_element.h
index 6d3f68b6..9aee4ccd 100644
--- a/third_party/blink/renderer/core/html/html_area_element.h
+++ b/third_party/blink/renderer/core/html/html_area_element.h
@@ -61,8 +61,7 @@
  private:
   void ParseAttribute(const AttributeModificationParams&) override;
   bool IsKeyboardFocusable() const override;
-  bool IsFocusable(bool disallow_layout_updates_for_accessibility_only =
-                       false) const override;
+  bool IsFocusable() const override;
   bool IsFocusableStyle() const override;
   void UpdateSelectionOnFocus(SelectionBehaviorOnFocus,
                               const FocusOptions*) override;
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.h b/third_party/blink/renderer/core/html/html_dialog_element.h
index 8751837c..f33b7fe 100644
--- a/third_party/blink/renderer/core/html/html_dialog_element.h
+++ b/third_party/blink/renderer/core/html/html_dialog_element.h
@@ -59,7 +59,9 @@
   void CloseWatcherFiredCancel(Event*);
   void CloseWatcherFiredClose();
 
-  bool SupportsFocus() const override { return true; }
+  bool IsFocusable() const override {
+    return isConnected() && IsFocusableStyleAfterUpdate();
+  }
 
   // https://html.spec.whatwg.org/C/#the-dialog-element
   // Chooses the focused element when show() or showModal() is invoked.
diff --git a/third_party/blink/renderer/core/html/image_document.cc b/third_party/blink/renderer/core/html/image_document.cc
index f74672d6..397962e6 100644
--- a/third_party/blink/renderer/core/html/image_document.cc
+++ b/third_party/blink/renderer/core/html/image_document.cc
@@ -138,11 +138,16 @@
 
   LocalFrame* frame = GetDocument()->GetFrame();
   Settings* settings = frame->GetSettings();
-  bool allow_image = !settings || settings->GetImagesEnabled();
-  if (auto* client = frame->GetContentSettingsClient())
-    allow_image = client->AllowImage(allow_image, GetDocument()->Url());
-  if (!allow_image)
+  bool allow_image_renderer = !settings || settings->GetImagesEnabled();
+  bool allow_image_content_setting = frame->GetContentSettings()->allow_image;
+  bool allow_image = allow_image_renderer && allow_image_content_setting;
+  if (!allow_image) {
+    auto* client = frame->GetContentSettingsClient();
+    if (client) {
+      client->DidNotAllowImage();
+    }
     return;
+  }
 
   if (!image_resource_) {
     ResourceRequest request(GetDocument()->Url());
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc
index 6f932e92..ea343bd 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -702,13 +702,11 @@
   return ShouldShowControls() || HTMLElement::SupportsFocus();
 }
 
-bool HTMLMediaElement::IsFocusable(
-    bool disallow_layout_updates_for_accessibility_only) const {
+bool HTMLMediaElement::IsFocusable() const {
   if (!SupportsFocus()) {
     return false;
   }
-  return !IsFullscreen() || HTMLElement::IsFocusable(
-                                disallow_layout_updates_for_accessibility_only);
+  return !IsFullscreen() || HTMLElement::IsFocusable();
 }
 
 bool HTMLMediaElement::IsKeyboardFocusable() const {
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h
index 21c4319..7ab5d43 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.h
+++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -494,8 +494,7 @@
   bool AreAuthorShadowsAllowed() const final { return false; }
 
   bool SupportsFocus() const final;
-  bool IsFocusable(
-      bool disallow_layout_updates_for_accessibility_only = false) const final;
+  bool IsFocusable() const final;
   bool IsKeyboardFocusable() const final;
   int DefaultTabIndex() const final;
   bool LayoutObjectIsNeeded(const DisplayStyle&) const override;
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
index b3340bd..fb9acb2 100644
--- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -221,7 +221,10 @@
   }
 
   if (old_style && Parent()) {
-    LayoutBlock* block = FindNonAnonymousContainingBlock(this);
+    LayoutBlock* block =
+        RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled()
+            ? InclusiveContainingBlock()
+            : FindNonAnonymousContainingBlock(this);
 
     if ((could_contain_fixed && !can_contain_fixed) ||
         (could_contain_absolute && !can_contain_absolute)) {
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index c75c84aa..d2952d8 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1685,6 +1685,9 @@
     AncestorSkipInfo* skip_info) const {
   NOT_DESTROYED();
   auto* container = ContainerForAbsolutePosition(skip_info);
+  if (RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled()) {
+    return container ? container->InclusiveContainingBlock(skip_info) : nullptr;
+  }
   return FindNonAnonymousContainingBlock(container, skip_info);
 }
 
@@ -1692,13 +1695,17 @@
     AncestorSkipInfo* skip_info) const {
   NOT_DESTROYED();
   auto* container = ContainerForFixedPosition(skip_info);
+  if (RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled()) {
+    return container ? container->InclusiveContainingBlock(skip_info) : nullptr;
+  }
   return FindNonAnonymousContainingBlock(container, skip_info);
 }
 
-const LayoutBlock* LayoutObject::InclusiveContainingBlock() const {
+LayoutBlock* LayoutObject::InclusiveContainingBlock(
+    AncestorSkipInfo* skip_info) {
   NOT_DESTROYED();
   auto* layout_block = DynamicTo<LayoutBlock>(this);
-  return layout_block ? layout_block : ContainingBlock();
+  return layout_block ? layout_block : ContainingBlock(skip_info);
 }
 
 const PaintLayer* LayoutObject::ContainingScrollContainerLayer(
@@ -1735,6 +1742,7 @@
 
 LayoutObject* LayoutObject::NonAnonymousAncestor() const {
   NOT_DESTROYED();
+  DCHECK(!RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled());
   LayoutObject* ancestor = Parent();
   while (ancestor && ancestor->IsAnonymous())
     ancestor = ancestor->Parent();
@@ -1752,6 +1760,7 @@
 
 bool LayoutObject::IsAnonymousNGMulticolInlineWrapper() const {
   NOT_DESTROYED();
+  DCHECK(!RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled());
   if (!IsLayoutNGBlockFlow() || !IsAnonymousBlock())
     return false;
 
@@ -1765,6 +1774,7 @@
 LayoutBlock* LayoutObject::FindNonAnonymousContainingBlock(
     LayoutObject* container,
     AncestorSkipInfo* skip_info) {
+  DCHECK(!RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled());
   // For inlines, we return the nearest non-anonymous enclosing
   // block. We don't try to return the inline itself. This allows us to avoid
   // having a positioned objects list in all LayoutInlines and lets us return a
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 3076257..26ddad3 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -2334,7 +2334,7 @@
   // or null if there is none.
   LayoutObject* NearestAncestorForElement() const;
 
-  const LayoutBlock* InclusiveContainingBlock() const;
+  LayoutBlock* InclusiveContainingBlock(AncestorSkipInfo* = nullptr);
 
   const LayoutBox* ContainingScrollContainer(
       bool ignore_layout_view_for_fixed_pos = false) const;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
index 742806d..5032b72 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
@@ -626,6 +626,7 @@
 void AdjustOffsetForSplitInline(const NGBlockNode& node,
                                 const NGBoxFragmentBuilder* container_builder,
                                 LogicalOffset& offset) {
+  DCHECK(!RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled());
   // Special case: oof css container is a split inline.
   // When css container spans multiple anonymous blocks, its dimensions can
   // only be computed by a block that is an ancestor of all fragments
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
index 2dc22099..640ff20 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
@@ -559,6 +559,7 @@
 
 LogicalOffset NGBoxFragmentBuilder::GetChildOffset(
     const LayoutObject* object) const {
+  DCHECK(!RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled());
   DCHECK(object);
 
   if (const FragmentItemsBuilder* items_builder = items_builder_) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
index 2f737980..f178277 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -1981,7 +1981,8 @@
       insets_to_store.ConvertToPhysical(candidate_writing_direction)
           .ConvertToLogical(node_info.default_writing_direction);
 
-  if (!container_builder_->IsBlockFragmentationContextRoot()) {
+  if (!RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled() &&
+      !container_builder_->IsBlockFragmentationContextRoot()) {
     // OOFs contained by an inline that's been split into continuations are
     // special, as their offset is relative to a fragment that's not the same as
     // their containing NG fragment; take a look inside
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
index 7e14ba4..d9d98a0 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -1403,7 +1403,8 @@
 
   if (ShouldIncludeBlockVisualOverflowForAnchorOnly(outline_type) &&
       !HasNonVisibleOverflow() && !HasControlClip(*this)) {
-    if (container->IsAnonymousBlock()) {
+    if (!RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled() &&
+        container->IsAnonymousBlock()) {
       const auto* container_box = DynamicTo<LayoutBox>(
           container->GetLayoutObject()->NonAnonymousAncestor());
       if (!container_box)
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index a3db9af..54734d5 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -332,6 +332,7 @@
   const base::flat_map<mojom::blink::RuntimeFeature, bool>
       modified_runtime_features;
   AtomicString cookie_deprecation_label;
+  mojom::RendererContentSettingsPtr content_settings;
 };
 
 // Asserts size of DocumentLoader, so that whenever a new attribute is added to
@@ -534,7 +535,8 @@
       load_with_storage_access_(params_->load_with_storage_access),
       browsing_context_group_info_(params_->browsing_context_group_info),
       modified_runtime_features_(std::move(params_->modified_runtime_features)),
-      cookie_deprecation_label_(params_->cookie_deprecation_label) {
+      cookie_deprecation_label_(params_->cookie_deprecation_label),
+      content_settings_(std::move(params_->content_settings)) {
   DCHECK(frame_);
   DCHECK(params_);
 
@@ -685,6 +687,7 @@
   params->load_with_storage_access = load_with_storage_access_;
   params->modified_runtime_features = modified_runtime_features_;
   params->cookie_deprecation_label = cookie_deprecation_label_;
+  params->content_settings = content_settings_->Clone();
   return params;
 }
 
@@ -3496,6 +3499,10 @@
   GetLocalFrameClient().DidObserveSubresourceLoad(subresource_load_metrics);
 }
 
+const mojom::RendererContentSettingsPtr& DocumentLoader::GetContentSettings() {
+  return content_settings_;
+}
+
 DEFINE_WEAK_IDENTIFIER_MAP(DocumentLoader)
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h
index c896149..039844d 100644
--- a/third_party/blink/renderer/core/loader/document_loader.h
+++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -476,6 +476,9 @@
     return cookie_deprecation_label_;
   }
 
+  // Gets the content settings for the current {frame, navigation commit} tuple.
+  const mojom::RendererContentSettingsPtr& GetContentSettings();
+
  protected:
   // Based on its MIME type, if the main document's response corresponds to an
   // MHTML archive, then every resources will be loaded from this archive.
@@ -847,6 +850,9 @@
   // Will be used in
   // //third_party/blink/renderer/modules/cookie_deprecation_label.
   const AtomicString cookie_deprecation_label_;
+
+  // Renderer-enforced content settings are stored on a per-document basis.
+  mojom::RendererContentSettingsPtr content_settings_;
 };
 
 DECLARE_WEAK_IDENTIFIER_MAP(DocumentLoader);
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 7a0e1283..de2c8fd 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/python.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//third_party/blink/renderer/bindings/bindings.gni")
diff --git a/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc b/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc
index 5e6795a..bfd7848b 100644
--- a/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc
@@ -279,9 +279,7 @@
      aria-details=details
      aria-invalid=true
      aria-errormessage=error>
-    <div role=listbox>
-      <div id=active role=option></div>
-    </div>
+    <div id=active role=option></div>
     <div id=active2 role=gridcell></div>
     <div id=details role=contentinfo></div>
     <div id=details2 role=form></div>
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
index f834ecff..4468e2e 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -293,7 +293,8 @@
     return list_marker->ListItem(*layout_object_)->GetNode();
   }
 
-  if (layout_object_->IsAnonymous()) {
+  if (!RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled() &&
+      layout_object_->IsAnonymous()) {
     if (LayoutBlock* layout_block =
             LayoutObject::FindNonAnonymousContainingBlock(layout_object_)) {
       return layout_block->GetNode();
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index 460dd668..cba665f 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -3535,6 +3535,10 @@
 
 bool AXObject::IsBlockedByAriaModalDialog(
     IgnoredReasons* ignored_reasons) const {
+  if (IsDetached()) {
+    return false;
+  }
+
   Element* active_aria_modal_dialog =
       AXObjectCache().GetActiveAriaModalDialog();
 
@@ -4203,10 +4207,14 @@
     return false;
   }
 
-  // We should not need style updates at this point.
+  // We should not need layout/style updates at this point.
   CHECK(!elem->NeedsStyleRecalc())
       << "\n* Element: " << elem << "\n* Object: " << ToString(true, true)
       << "\n* LayoutObject: " << GetLayoutObject();
+  CHECK(
+      !GetDocument()->NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(*elem))
+      << "\n* Element: " << elem << "\n* Object: " << ToString(true, true)
+      << "\n* LayoutObject: " << GetLayoutObject();
 
   // Focusable: element supports focus.
   return elem->SupportsFocus();
@@ -4218,13 +4226,13 @@
   }
 
   Element& element = *GetElement();
+  Document& document = *GetDocument();
   CHECK(!element.NeedsStyleRecalc())
       << "\n* Element: " << element << "\n* Object: " << ToString(true, true)
       << "\n* LayoutObject: " << GetLayoutObject();
-  if (!element.IsFocusable(
-          /*disallow_layout_updates_for_accessibility_only*/ true)) {
-    return false;
-  }
+  CHECK(!document.NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(element))
+      << "\n* Element: " << element << "\n* Object: " << ToString(true, true)
+      << "\n* LayoutObject: " << GetLayoutObject();
   return element.IsKeyboardFocusable();
 }
 
@@ -4945,6 +4953,9 @@
         AtomicString("ARIA-GRABBED"),
         AtomicString("ARIA-HIDDEN"),  // For aria-hidden=false.
         AtomicString("ARIA-KEYSHORTCUTS"),
+        AtomicString("ARIA-LABEL"),
+        AtomicString("ARIA-LABELEDBY"),
+        AtomicString("ARIA-LABELLEDBY"),
         AtomicString("ARIA-LIVE"),
         AtomicString("ARIA-OWNS"),
         AtomicString("ARIA-RELEVANT"),
@@ -5171,13 +5182,6 @@
       role = ax::mojom::blink::Role::kComboBoxMenuButton;
   }
 
-  // Distinguish orphaned options out of the listbox context
-  if (role == ax::mojom::blink::Role::kListBoxOption) {
-    AXObject* parent = ParentObjectIncludedInTree();
-    if (parent && parent->RoleValue() != ax::mojom::blink::Role::kListBox)
-      return ax::mojom::blink::Role::kUnknown;
-  }
-
   return role;
 }
 
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
index 0ccfef23..7c8e5e3 100644
--- a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
+++ b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
@@ -305,23 +305,13 @@
     return;
   }
 
-  bool has_unsanitized_html =
-      RuntimeEnabledFeatures::ClipboardUnsanitizedContentEnabled() &&
-      base::ranges::any_of(clipboard_item_data_with_promises_,
-                           [](const auto& type_and_promise_to_blob) {
-                             return type_and_promise_to_blob.first ==
-                                    kMimeTypeTextHTML;
-                           });
-
-  DCHECK(has_unsanitized_html ||
-         RuntimeEnabledFeatures::ClipboardCustomFormatsEnabled() ||
+  DCHECK(RuntimeEnabledFeatures::ClipboardCustomFormatsEnabled() ||
          custom_format_items_.empty());
 
   // Input in standard formats is sanitized, so the write will be sanitized
-  // unless the HTML is unsanitized or there are custom formats.
+  // unless there are custom formats.
   RequestPermission(mojom::blink::PermissionName::CLIPBOARD_WRITE,
-                    /*will_be_sanitized=*/
-                    !has_unsanitized_html && custom_format_items_.empty(),
+                    /*will_be_sanitized=*/custom_format_items_.empty(),
                     WTF::BindOnce(&ClipboardPromise::HandleWriteWithPermission,
                                   WrapPersistent(this)));
 }
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_proxy.cc b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_proxy.cc
index 16419f2e..aa16bbc 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_proxy.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_proxy.cc
@@ -17,8 +17,7 @@
       credential_manager_(window.GetExecutionContext()),
       webotp_service_(window.GetExecutionContext()),
       payment_credential_(window.GetExecutionContext()),
-      federated_auth_request_(window.GetExecutionContext()),
-      fedcm_logout_request_(window.GetExecutionContext()) {}
+      federated_auth_request_(window.GetExecutionContext()) {}
 
 CredentialManagerProxy::~CredentialManagerProxy() = default;
 
@@ -93,27 +92,12 @@
   return federated_auth_request_.get();
 }
 
-mojom::blink::FederatedAuthRequest*
-CredentialManagerProxy::FedCmLogoutRpsRequest() {
-  BindRemoteForFedCm(
-      fedcm_logout_request_,
-      WTF::BindOnce(&CredentialManagerProxy::OnFedCmLogoutConnectionError,
-                    WrapWeakPersistent(this)));
-  return fedcm_logout_request_.get();
-}
-
 void CredentialManagerProxy::OnFederatedAuthRequestConnectionError() {
   federated_auth_request_.reset();
   // TODO(crbug.com/1275769): Cache the resolver and resolve the promise with an
   // appropriate error message.
 }
 
-void CredentialManagerProxy::OnFedCmLogoutConnectionError() {
-  fedcm_logout_request_.reset();
-  // TODO(crbug.com/1275769): Cache the resolver and resolve the promise with an
-  // appropriate error message.
-}
-
 // TODO(crbug.com/1372275): Replace From(ScriptState*) with
 // From(ExecutionContext*)
 // static
@@ -155,7 +139,6 @@
   visitor->Trace(webotp_service_);
   visitor->Trace(payment_credential_);
   visitor->Trace(federated_auth_request_);
-  visitor->Trace(fedcm_logout_request_);
   Supplement<LocalDOMWindow>::Trace(visitor);
 }
 
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_proxy.h b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_proxy.h
index 78e83af..9a12bb8 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_proxy.h
+++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_proxy.h
@@ -52,8 +52,6 @@
 
   mojom::blink::FederatedAuthRequest* FederatedAuthRequest();
 
-  mojom::blink::FederatedAuthRequest* FedCmLogoutRpsRequest();
-
   void Trace(Visitor*) const override;
 
   // Must be called only with argument representing a valid
@@ -68,14 +66,12 @@
   void BindRemoteForFedCm(HeapMojoRemote<Interface>& remote,
                           base::OnceClosure disconnect_closure);
   void OnFederatedAuthRequestConnectionError();
-  void OnFedCmLogoutConnectionError();
 
   HeapMojoRemote<mojom::blink::Authenticator> authenticator_;
   HeapMojoRemote<mojom::blink::CredentialManager> credential_manager_;
   HeapMojoRemote<mojom::blink::WebOTPService> webotp_service_;
   HeapMojoRemote<payments::mojom::blink::PaymentCredential> payment_credential_;
   HeapMojoRemote<mojom::blink::FederatedAuthRequest> federated_auth_request_;
-  HeapMojoRemote<mojom::blink::FederatedAuthRequest> fedcm_logout_request_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
index 4f8693e8..973fa332 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
@@ -28,7 +28,6 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_digital_credential_field_requirement.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_digital_credential_provider.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_digital_credential_selector.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_identity_credential_logout_r_ps_request.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_identity_credential_request_options_context.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_identity_credential_request_options_mode.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_identity_credential_revoke_options.h"
@@ -86,8 +85,6 @@
 using blink::mojom::blink::IdentityUserInfo;
 using blink::mojom::blink::IdentityUserInfoPtr;
 using blink::mojom::blink::LargeBlobSupport;
-using blink::mojom::blink::LogoutRpsRequest;
-using blink::mojom::blink::LogoutRpsRequestPtr;
 using blink::mojom::blink::PRFValues;
 using blink::mojom::blink::PRFValuesPtr;
 using blink::mojom::blink::PublicKeyCredentialCreationOptionsPtr;
@@ -462,17 +459,6 @@
 }
 
 // static
-LogoutRpsRequestPtr
-TypeConverter<LogoutRpsRequestPtr, blink::IdentityCredentialLogoutRPsRequest>::
-    Convert(const blink::IdentityCredentialLogoutRPsRequest& request) {
-  auto mojo_request = LogoutRpsRequest::New();
-
-  mojo_request->url = blink::KURL(request.url());
-  mojo_request->account_id = request.accountId();
-  return mojo_request;
-}
-
-// static
 PublicKeyCredentialUserEntityPtr
 TypeConverter<PublicKeyCredentialUserEntityPtr,
               blink::PublicKeyCredentialUserEntity>::
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h
index f305a759..61746a15 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h
+++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h
@@ -25,7 +25,6 @@
 class CableAuthenticationData;
 class Credential;
 class IdentityCredentialRevokeOptions;
-class IdentityCredentialLogoutRPsRequest;
 class IdentityProviderConfig;
 class IdentityProviderRequestOptions;
 class IdentityUserInfo;
@@ -140,13 +139,6 @@
 };
 
 template <>
-struct TypeConverter<blink::mojom::blink::LogoutRpsRequestPtr,
-                     blink::IdentityCredentialLogoutRPsRequest> {
-  static blink::mojom::blink::LogoutRpsRequestPtr Convert(
-      const blink::IdentityCredentialLogoutRPsRequest&);
-};
-
-template <>
 struct TypeConverter<blink::mojom::blink::PublicKeyCredentialUserEntityPtr,
                      blink::PublicKeyCredentialUserEntity> {
   static blink::mojom::blink::PublicKeyCredentialUserEntityPtr Convert(
diff --git a/third_party/blink/renderer/modules/credentialmanagement/identity_credential.cc b/third_party/blink/renderer/modules/credentialmanagement/identity_credential.cc
index f7c669c..85f0e3a 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/identity_credential.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/identity_credential.cc
@@ -17,7 +17,6 @@
 namespace blink {
 
 namespace {
-using mojom::blink::LogoutRpsStatus;
 using mojom::blink::RequestTokenStatus;
 using mojom::blink::RevokeStatus;
 
@@ -32,21 +31,6 @@
   kMaxValue = kFailedOrigin
 };
 
-void OnLogoutRpsResponse(ScriptPromiseResolver* resolver,
-                         LogoutRpsStatus status) {
-  // TODO(kenrb); There should be more thought put into how this API works.
-  // Returning success or failure doesn't have a lot of meaning. If some
-  // logout attempts fail and others succeed, and even different attempts
-  // fail for different reasons, how does that get conveyed to the caller?
-  if (status != LogoutRpsStatus::kSuccess) {
-    resolver->Reject(MakeGarbageCollected<DOMException>(
-        DOMExceptionCode::kNetworkError, "Error logging out endpoints."));
-
-    return;
-  }
-  resolver->Resolve();
-}
-
 void OnRevoke(ScriptPromiseResolver* resolver, RevokeStatus status) {
   if (status != RevokeStatus::kSuccess) {
     resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -112,65 +96,6 @@
 }
 
 // static
-ScriptPromise IdentityCredential::logoutRPs(
-    ScriptState* script_state,
-    const HeapVector<Member<IdentityCredentialLogoutRPsRequest>>&
-        logout_endpoints) {
-  if (!RuntimeEnabledFeatures::FedCmIdpSignoutEnabled(
-          ExecutionContext::From(script_state))) {
-    return ScriptPromise::RejectWithDOMException(
-        script_state, MakeGarbageCollected<DOMException>(
-                          DOMExceptionCode::kNotSupportedError,
-                          "FedCM IdpSignout flag in about:flags not enabled."));
-  }
-
-  // |FedCmEnabled| is not implied by |FedCmIdpSignoutEnabled| when the latter
-  // is set via runtime flags (rather than about:flags).
-  if (!RuntimeEnabledFeatures::FedCmEnabled(
-          ExecutionContext::From(script_state))) {
-    return ScriptPromise::RejectWithDOMException(
-        script_state, MakeGarbageCollected<DOMException>(
-                          DOMExceptionCode::kNotSupportedError,
-                          "FedCM flag in about:flags not enabled."));
-  }
-
-  if (logout_endpoints.empty()) {
-    return ScriptPromise();
-  }
-
-  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
-  ScriptPromise promise = resolver->Promise();
-
-  ContentSecurityPolicy* policy =
-      resolver->GetExecutionContext()
-          ->GetContentSecurityPolicyForCurrentWorld();
-  Vector<mojom::blink::LogoutRpsRequestPtr> logout_requests;
-  for (auto& request : logout_endpoints) {
-    auto logout_request = mojom::blink::LogoutRpsRequest::From(*request);
-    if (!logout_request->url.IsValid()) {
-      resolver->Reject(MakeGarbageCollected<DOMException>(
-          DOMExceptionCode::kSyntaxError, "Invalid logout endpoint URL."));
-      return promise;
-    }
-    if (IsRejectingPromiseDueToCSP(policy, resolver, logout_request->url))
-      return promise;
-    if (logout_request->account_id.empty()) {
-      resolver->Reject(MakeGarbageCollected<DOMException>(
-          DOMExceptionCode::kSyntaxError, "Account ID cannot be empty."));
-      return promise;
-    }
-    logout_requests.push_back(std::move(logout_request));
-  }
-
-  auto* fedcm_logout_request =
-      CredentialManagerProxy::From(script_state)->FedCmLogoutRpsRequest();
-  fedcm_logout_request->LogoutRps(
-      std::move(logout_requests),
-      WTF::BindOnce(&OnLogoutRpsResponse, WrapPersistent(resolver)));
-  return promise;
-}
-
-// static
 ScriptPromise IdentityCredential::revoke(
     ScriptState* script_state,
     const blink::IdentityCredentialRevokeOptions* options,
diff --git a/third_party/blink/renderer/modules/credentialmanagement/identity_credential.h b/third_party/blink/renderer/modules/credentialmanagement/identity_credential.h
index 75ea33a..0759bfc2 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/identity_credential.h
+++ b/third_party/blink/renderer/modules/credentialmanagement/identity_credential.h
@@ -36,10 +36,6 @@
   const String& token() const { return token_; }
   const bool& isAutoSelected() const { return is_auto_selected_; }
 
-  static ScriptPromise logoutRPs(
-      ScriptState*,
-      const HeapVector<Member<IdentityCredentialLogoutRPsRequest>>&);
-
   static ScriptPromise revoke(ScriptState*,
                               const IdentityCredentialRevokeOptions* options,
                               ExceptionState&);
diff --git a/third_party/blink/renderer/modules/credentialmanagement/identity_credential.idl b/third_party/blink/renderer/modules/credentialmanagement/identity_credential.idl
index 42aedf5..197e54a0 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/identity_credential.idl
+++ b/third_party/blink/renderer/modules/credentialmanagement/identity_credential.idl
@@ -20,10 +20,6 @@
     [RuntimeEnabled=FedCmAutoSelectedFlag]
     readonly attribute boolean isAutoSelected;
 
-    // Allows IDPs to logout the user out of all of the logged in RPs.
-    [RuntimeEnabled=FedCmIdpSignout, CallWith=ScriptState, MeasureAs=FedCmLogoutRps]
-    static Promise<void> logoutRPs(optional sequence<IdentityCredentialLogoutRPsRequest> logout_requests = []);
-
     // https://fedidcg.github.io/FedCM/#browser-api-revocation
     [RuntimeEnabled=FedCmRevoke, CallWith=ScriptState, RaisesException, MeasureAs=FedCmRevoke] static Promise<void> revoke(optional IdentityCredentialRevokeOptions options = {});
 
diff --git a/third_party/blink/renderer/modules/sensor/testing/internals_sensor.cc b/third_party/blink/renderer/modules/sensor/testing/internals_sensor.cc
index 05ab132..9cf5d10 100644
--- a/third_party/blink/renderer/modules/sensor/testing/internals_sensor.cc
+++ b/third_party/blink/renderer/modules/sensor/testing/internals_sensor.cc
@@ -63,12 +63,10 @@
   auto metadata = device::mojom::blink::VirtualSensorMetadata::New();
   metadata->available = options->connected();
   if (options->hasMinSamplingFrequency()) {
-    metadata->minimum_frequency = device::mojom::blink::NullableDouble::New(
-        options->minSamplingFrequency().value());
+    metadata->minimum_frequency = options->minSamplingFrequency().value();
   }
   if (options->hasMaxSamplingFrequency()) {
-    metadata->maximum_frequency = device::mojom::blink::NullableDouble::New(
-        options->maxSamplingFrequency().value());
+    metadata->maximum_frequency = options->maxSamplingFrequency().value();
   }
   return metadata;
 }
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc
index 936c605..0289f6a 100644
--- a/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc
+++ b/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc
@@ -45,7 +45,7 @@
   audio_data->allocationSize(options, IGNORE_EXCEPTION_FOR_TESTING);
 
   AllowSharedBufferSource* destination =
-      MakeAllowSharedBufferSource(proto.copy_to().destination());
+      MakeAllowSharedBufferSource(proto.copy_to().destination()).source;
   DCHECK(destination);
 
   // The returned promise will be fulfilled synchronously since the source frame
diff --git a/third_party/blink/renderer/modules/webcodecs/fuzzer_inputs.proto b/third_party/blink/renderer/modules/webcodecs/fuzzer_inputs.proto
index 97f11a5..584753a 100644
--- a/third_party/blink/renderer/modules/webcodecs/fuzzer_inputs.proto
+++ b/third_party/blink/renderer/modules/webcodecs/fuzzer_inputs.proto
@@ -20,6 +20,9 @@
   optional ViewType view_type = 3;
   optional uint32 view_offset = 4;
   optional uint32 view_length = 5;
+
+  // Transfer ArrayBuffer into ctor
+  optional bool transfer = 6;
 }
 
 message DOMRectInit {
@@ -233,10 +236,16 @@
   repeated bytes channels = 4;
 
   required AudioSampleFormat format = 5;
+
+  // Transfer ArrayBuffer into ctor
+  optional bool transfer = 6;
 }
 
 message EncodeVideo {
-  optional VideoFrameBitmapInit frame = 1;
+  oneof Frames {
+    VideoFrameBitmapInit frame = 1;
+    VideoFrameBufferInitInvocation frame_from_buffer = 3;
+  }
   message EncodeOptionsForAv1 {
     optional uint32 quantizer = 1;
   };
diff --git a/third_party/blink/renderer/modules/webcodecs/fuzzer_seed_corpus/video_encoder/encode_transfer.textproto b/third_party/blink/renderer/modules/webcodecs/fuzzer_seed_corpus/video_encoder/encode_transfer.textproto
new file mode 100644
index 0000000..3b541c4
--- /dev/null
+++ b/third_party/blink/renderer/modules/webcodecs/fuzzer_seed_corpus/video_encoder/encode_transfer.textproto
@@ -0,0 +1,55 @@
+invocations: [
+  {
+    configure {
+      codec: 'avc1.42001E',
+      acceleration: DENY,
+      bitrate: 1500000,
+      framerate: 25,
+      width: 360,
+      height: 240,
+      bitrate_mode: CONSTANT,
+    }
+  },
+  {
+    encode {
+      frame_from_buffer {
+        data {
+          length: 129600,
+          shared: false,
+          transfer: true
+        }
+        init {
+          format: I420,
+          layout: [
+            {offset: 0, stride: 360},
+            {offset: 86400, stride: 180},
+            {offset: 108000, stride: 180}
+          ],
+          timestamp: 0,
+          duration: 100000,
+          coded_width: 360,
+          coded_height: 240,
+          visible_rect {x: 0, y: 0, width: 360, height: 240}
+          display_width: 360,
+          display_height: 240
+        }
+      }
+    }
+  },
+  {
+    flush {}
+  },
+  {
+    configure {
+      codec: 'vp8',
+      acceleration: DENY,
+      bitrate: 500000,
+      framerate: 30,
+      width: 640,
+      height: 480,
+    }
+  },
+  {
+    close {}
+  }
+]
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
index 7b7469e..c7ed9d1 100644
--- a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
+++ b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
@@ -344,8 +344,9 @@
   return options;
 }
 
-AllowSharedBufferSource* MakeAllowSharedBufferSource(
+BufferAndSource MakeAllowSharedBufferSource(
     const wc_fuzzer::AllowSharedBufferSource& proto) {
+  BufferAndSource result = {};
   size_t length =
       std::min(static_cast<size_t>(proto.length()), kMaxBufferLength);
 
@@ -353,7 +354,11 @@
   if (proto.shared()) {
     buffer = DOMSharedArrayBuffer::Create(static_cast<unsigned>(length), 1);
   } else {
-    buffer = DOMArrayBuffer::Create(length, 1);
+    auto* array_buffer = DOMArrayBuffer::Create(length, 1);
+    buffer = array_buffer;
+    if (proto.transfer()) {
+      result.buffer = array_buffer;
+    }
   }
   DCHECK(buffer);
 
@@ -363,25 +368,28 @@
       std::min(static_cast<size_t>(proto.view_length()), length - view_offset);
   switch (proto.view_type()) {
     case wc_fuzzer::AllowSharedBufferSource_ViewType_NONE:
-      return MakeGarbageCollected<AllowSharedBufferSource>(buffer);
+      result.source = MakeGarbageCollected<AllowSharedBufferSource>(buffer);
+      break;
     case wc_fuzzer::AllowSharedBufferSource_ViewType_INT8:
-      return MakeGarbageCollected<AllowSharedBufferSource>(
+      result.source = MakeGarbageCollected<AllowSharedBufferSource>(
           MaybeShared<DOMInt8Array>(
               DOMInt8Array::Create(buffer, view_offset, view_length)));
+      break;
     case wc_fuzzer::AllowSharedBufferSource_ViewType_UINT32:
       // View must be element-aligned and is sized by element count.
       view_offset = std::min(view_offset, length / 4) * 4;
       view_length = std::min(view_length, length / 4 - view_offset / 4);
-      return MakeGarbageCollected<AllowSharedBufferSource>(
+      result.source = MakeGarbageCollected<AllowSharedBufferSource>(
           MaybeShared<DOMUint32Array>(
               DOMUint32Array::Create(buffer, view_offset, view_length)));
+      break;
     case wc_fuzzer::AllowSharedBufferSource_ViewType_DATA:
-      return MakeGarbageCollected<AllowSharedBufferSource>(
+      result.source = MakeGarbageCollected<AllowSharedBufferSource>(
           MaybeShared<DOMDataView>(
               DOMDataView::Create(buffer, view_offset, view_length)));
   }
 
-  NOTREACHED();
+  return result;
 }
 
 PlaneLayout* MakePlaneLayout(const wc_fuzzer::PlaneLayout& proto) {
@@ -403,7 +411,7 @@
 VideoFrame* MakeVideoFrame(
     ScriptState* script_state,
     const wc_fuzzer::VideoFrameBufferInitInvocation& proto) {
-  AllowSharedBufferSource* data = MakeAllowSharedBufferSource(proto.data());
+  BufferAndSource data = MakeAllowSharedBufferSource(proto.data());
   VideoFrameBufferInit* init = VideoFrameBufferInit::Create();
 
   switch (proto.init().format()) {
@@ -457,7 +465,13 @@
   if (proto.init().has_display_height())
     init->setDisplayHeight(proto.init().display_height());
 
-  return VideoFrame::Create(script_state, data, init,
+  if (data.buffer) {
+    HeapVector<Member<DOMArrayBuffer>> transfer;
+    transfer.push_back(data.buffer);
+    init->setTransfer(std::move(transfer));
+  }
+
+  return VideoFrame::Create(script_state, data.source, init,
                             IGNORE_EXCEPTION_FOR_TESTING);
 }
 
@@ -534,6 +548,12 @@
   init->setFormat(format);
   init->setData(MakeGarbageCollected<AllowSharedBufferSource>(buffer));
 
+  if (proto.transfer()) {
+    HeapVector<Member<DOMArrayBuffer>> transfer;
+    transfer.push_back(buffer);
+    init->setTransfer(std::move(transfer));
+  }
+
   return AudioData::Create(script_state, init, IGNORE_EXCEPTION_FOR_TESTING);
 }
 
diff --git a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h
index f6af965..8fd18da 100644
--- a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h
+++ b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h
@@ -66,7 +66,12 @@
     ScriptState* script_state,
     const wc_fuzzer::EncodedAudioChunk& proto);
 
-AllowSharedBufferSource* MakeAllowSharedBufferSource(
+struct BufferAndSource {
+  UntracedMember<DOMArrayBuffer> buffer;
+  UntracedMember<AllowSharedBufferSource> source;
+};
+
+BufferAndSource MakeAllowSharedBufferSource(
     const wc_fuzzer::AllowSharedBufferSource& proto);
 
 PlaneLayout* MakePlaneLayout(const wc_fuzzer::PlaneLayout& proto);
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc
index 1a66890..89c89f71 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc
@@ -37,7 +37,6 @@
     page_holder->GetFrame().GetSettings()->SetScriptEnabled(true);
     return page_holder.release();
   }();
-
   // Request a full GC upon returning.
   auto scoped_gc =
       MakeScopedGarbageCollectionRequest(test_support.GetIsolate());
@@ -93,8 +92,21 @@
             break;
           }
           case wc_fuzzer::VideoEncoderApiInvocation::kEncode: {
-            VideoFrame* frame =
-                MakeVideoFrame(script_state, invocation.encode().frame());
+            VideoFrame* frame;
+            switch (invocation.encode().Frames_case()) {
+              case wc_fuzzer::EncodeVideo::kFrame:
+                frame =
+                    MakeVideoFrame(script_state, invocation.encode().frame());
+                break;
+              case wc_fuzzer::EncodeVideo::kFrameFromBuffer:
+                frame = MakeVideoFrame(script_state,
+                                       invocation.encode().frame_from_buffer());
+                break;
+              default:
+                frame = nullptr;
+                break;
+            }
+
             // Often the fuzzer input will be too crazy to produce a valid frame
             // (e.g. bitmap width > bitmap length). In these cases, return early
             // to discourage this sort of fuzzer input. WebIDL doesn't allow
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc
index 3a5db4f..65bf41f 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc
@@ -58,7 +58,7 @@
   video_frame->allocationSize(options, IGNORE_EXCEPTION_FOR_TESTING);
 
   AllowSharedBufferSource* destination =
-      MakeAllowSharedBufferSource(proto.copy_to().destination());
+      MakeAllowSharedBufferSource(proto.copy_to().destination()).source;
   DCHECK(destination);
 
   // The returned promise will be fulfilled synchronously since the source frame
diff --git a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc
index ada0925..2481adca 100644
--- a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc
+++ b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc
@@ -75,9 +75,11 @@
     auto* sii = SharedImageInterface();
     if (!sii || !gmb_manager_)
       return;
-    mailbox = sii->CreateSharedImage(
+    auto client_shared_image = sii->CreateSharedImage(
         gpu_memory_buffer, gmb_manager_, plane, color_space, surface_origin,
         alpha_type, usage, "WebGraphicsContext2DVideoFramePool");
+    CHECK(client_shared_image);
+    mailbox = client_shared_image->mailbox();
     sync_token = sii->GenVerifiedSyncToken();
   }
 
diff --git a/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.cc
index 95658265..4fcdff7f 100644
--- a/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.cc
+++ b/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.cc
@@ -101,13 +101,13 @@
 
     switch (codec_creation_result) {
       case SkCodec::kSuccess: {
+        segment_stream_ = segment_stream_ptr;
         // SkGifDecoder::Decode will read enough of the image to get the image
         // size.
         SkImageInfo image_info = codec_->getInfo();
         SetSize(static_cast<unsigned>(image_info.width()),
                 static_cast<unsigned>(image_info.height()));
 
-        segment_stream_ = segment_stream_ptr;
         return;
       }
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index c15de220..59e84c2 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1714,13 +1714,6 @@
       browser_process_read_access: true,
     },
     {
-      name: "FedCmIdpSignout",
-      depends_on: ["FedCm"],
-      public: true,
-      status: "test",
-      base_feature: "none",
-    },
-    {
       name: "FedCmMultipleIdentityProviders",
       depends_on: ["FedCm"],
       base_feature: "none",
@@ -2301,6 +2294,10 @@
       name: "LayoutIgnoreMarginsForSticky",
     },
     {
+      name: "LayoutNewContainingBlock",
+      status: "stable",
+    },
+    {
       name: "LayoutNewOverflowLogic",
       status: "stable",
     },
diff --git a/third_party/blink/renderer/platform/theme/web_theme_engine_default.cc b/third_party/blink/renderer/platform/theme/web_theme_engine_default.cc
index 06fc2f5..0f1dc563 100644
--- a/third_party/blink/renderer/platform/theme/web_theme_engine_default.cc
+++ b/third_party/blink/renderer/platform/theme/web_theme_engine_default.cc
@@ -265,8 +265,13 @@
 }
 
 void WebThemeEngineDefault::GetOverlayScrollbarStyle(ScrollbarStyle* style) {
-  style->fade_out_delay = ui::kOverlayScrollbarFadeDelay;
-  style->fade_out_duration = ui::kOverlayScrollbarFadeDuration;
+  if (IsFluentOverlayScrollbarEnabled()) {
+    style->fade_out_delay = ui::kFluentOverlayScrollbarFadeDelay;
+    style->fade_out_duration = ui::kFluentOverlayScrollbarFadeDuration;
+  } else {
+    style->fade_out_delay = ui::kOverlayScrollbarFadeDelay;
+    style->fade_out_duration = ui::kOverlayScrollbarFadeDuration;
+  }
   style->idle_thickness_scale = ui::kOverlayScrollbarIdleThicknessScale;
   // The other fields in this struct are used only on Android to draw solid
   // color scrollbars. On other platforms the scrollbars are painted in
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 68bbcb5..0610fba 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
@@ -608,24 +608,24 @@
 #endif
       CHECK_EQ(gpu_memory_buffer_->GetFormat(),
                gfx::BufferFormat::YUV_420_BIPLANAR);
+      scoped_refptr<gpu::ClientSharedImage> client_shared_image;
       if (create_multiplanar_image) {
-        auto client_shared_image = sii->CreateSharedImage(
+        client_shared_image = sii->CreateSharedImage(
             multiplanar_si_format, gpu_memory_buffer_->GetSize(),
             frame_info_->color_space, kTopLeft_GrSurfaceOrigin,
             kPremul_SkAlphaType, usage, "VideoCaptureFrameBuffer",
             gpu_memory_buffer_->CloneHandle());
-        CHECK(client_shared_image);
-        buffer_context_->gmb_resources()->mailboxes[plane] =
-            client_shared_image->mailbox();
+
       } else {
-        buffer_context_->gmb_resources()->mailboxes[plane] =
-            sii->CreateSharedImage(
-                gpu_memory_buffer_.get(),
-                buffer_context_->gpu_factories()->GpuMemoryBufferManager(),
-                planes[plane], frame_info_->color_space,
-                kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, usage,
-                "VideoCaptureFrameBuffer");
+        client_shared_image = sii->CreateSharedImage(
+            gpu_memory_buffer_.get(),
+            buffer_context_->gpu_factories()->GpuMemoryBufferManager(),
+            planes[plane], frame_info_->color_space, kTopLeft_GrSurfaceOrigin,
+            kPremul_SkAlphaType, usage, "VideoCaptureFrameBuffer");
       }
+      CHECK(client_shared_image);
+      buffer_context_->gmb_resources()->mailboxes[plane] =
+          client_shared_image->mailbox();
     } else {
       sii->UpdateSharedImage(
           buffer_context_->gmb_resources()->release_sync_token,
diff --git a/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc b/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
index d59b667..a084ec4 100644
--- a/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
+++ b/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
@@ -101,9 +101,11 @@
     auto* sii = SharedImageInterface();
     if (!sii)
       return;
-    mailbox = sii->CreateSharedImage(
+    auto client_shared_image = sii->CreateSharedImage(
         gpu_memory_buffer, GpuMemoryBufferManager(), plane, color_space,
         surface_origin, alpha_type, usage, "WebRTCVideoFramePool");
+    CHECK(client_shared_image);
+    mailbox = client_shared_image->mailbox();
     sync_token = sii->GenVerifiedSyncToken();
   }
 
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 b7e8b531..0e5ecb9 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
@@ -72,9 +72,15 @@
 
 #if !BUILDFLAG(IS_ANDROID)
   if (ui::IsOverlayScrollbarEnabled()) {
-    settings.scrollbar_fade_delay = ui::kOverlayScrollbarFadeDelay;
-    settings.scrollbar_fade_duration = ui::kOverlayScrollbarFadeDuration;
     settings.idle_thickness_scale = ui::kOverlayScrollbarIdleThicknessScale;
+    if (ui::IsFluentOverlayScrollbarEnabled()) {
+      settings.scrollbar_fade_delay = ui::kFluentOverlayScrollbarFadeDelay;
+      settings.scrollbar_fade_duration =
+          ui::kFluentOverlayScrollbarFadeDuration;
+    } else {
+      settings.scrollbar_fade_delay = ui::kOverlayScrollbarFadeDelay;
+      settings.scrollbar_fade_duration = ui::kOverlayScrollbarFadeDuration;
+    }
   }
 #endif  // !BUILDFLAG(IS_ANDROID)
 
@@ -607,11 +613,14 @@
     settings.scrollbar_flash_after_any_scroll_update =
         !settings.enable_fluent_overlay_scrollbar;
     // Avoid animating in web tests to improve reliability.
-    if (settings.enable_fluent_overlay_scrollbar &&
-        WebTestSupport::IsRunningWebTest()) {
-      settings.scrollbar_thinning_duration = base::Milliseconds(0);
-      settings.scrollbar_fade_delay = base::Milliseconds(0);
-      settings.scrollbar_fade_duration = base::Milliseconds(0);
+    if (settings.enable_fluent_overlay_scrollbar) {
+      settings.scrollbar_thinning_duration =
+          ui::kFluentOverlayScrollbarThinningDuration;
+      if (WebTestSupport::IsRunningWebTest()) {
+        settings.scrollbar_thinning_duration = base::Milliseconds(0);
+        settings.scrollbar_fade_delay = base::Milliseconds(0);
+        settings.scrollbar_fade_duration = base::Milliseconds(0);
+      }
     }
   }
 #endif  // BUILDFLAG(IS_ANDROID)
diff --git a/third_party/blink/tools/blinkpy/common/config/builders.json b/third_party/blink/tools/blinkpy/common/config/builders.json
index 49dfa09..fc92eec 100644
--- a/third_party/blink/tools/blinkpy/common/config/builders.json
+++ b/third_party/blink/tools/blinkpy/common/config/builders.json
@@ -55,6 +55,15 @@
         "is_try_builder": true,
         "is_cq_builder": true
     },
+    "linux-wpt-fyi-rel": {
+        "main": "chromium.fyi",
+        "port_name": "chrome",
+        "specifiers": ["Chrome", "Release"],
+        "is_try_builder": true,
+        "steps": {
+            "wpt_tests_suite (with patch)": {}
+        }
+    },
     "linux-blink-rel": {
         "main": "tryserver.blink",
         "port_name": "linux",
diff --git a/third_party/blink/tools/blinkpy/web_tests/builder_list.py b/third_party/blink/tools/blinkpy/web_tests/builder_list.py
index 8871c2b..1b05b29 100644
--- a/third_party/blink/tools/blinkpy/web_tests/builder_list.py
+++ b/third_party/blink/tools/blinkpy/web_tests/builder_list.py
@@ -119,9 +119,9 @@
     def try_bots_with_cq_mirror(self):
         """Returns a sorted list of (try_builder_names, cq_mirror_builder_names).
 
-        When all steps in a blink-rel trybot exist in a cq trybot and the port
-        name matches, we say that blink-rel trybot has a cq mirror, and thus
-        there is no need to trigger both the blink-rel trybot and its cq mirror.
+        When all steps in a cq trybot exist in a blink-rel trybot and the port
+        name matches, we say that blink-rel trybot has a cq mirror, and thus there
+        is no need to trigger the cq trybot together with the blink-rel trybot.
 
         As of today, this should return:
         [("linux-blink-rel", "linux-rel"),
@@ -138,8 +138,9 @@
                 if (self.port_name_for_builder_name(cq_builder_name) !=
                         self.port_name_for_builder_name(builder_name)):
                     continue
-                cq_step_names = self.step_names_for_builder(cq_builder_name)
-                if step_names.issubset(cq_step_names):
+                cq_step_names = set(
+                    self.step_names_for_builder(cq_builder_name))
+                if cq_step_names.issubset(step_names):
                     rv.append((builder_name, cq_builder_name))
                     break
         return rv
diff --git a/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py b/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
index dcdd094..5adcdfa 100644
--- a/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/builder_list_unittest.py
@@ -180,13 +180,13 @@
 
     def test_builders_for_rebaselining(self):
         builders = self.sample_builder_list()
-        self.assertEqual({'Try A', 'Try B', 'Flag Specific C', 'some-wpt-bot'},
-                         builders.builders_for_rebaselining())
+        self.assertEqual(
+            {'Try A', 'Try B', 'Flag Specific C', 'CQ Try C', 'some-wpt-bot'},
+            builders.builders_for_rebaselining())
 
     def test_try_bots_with_cq_mirror(self):
         builders = self.sample_builder_list()
-        try_and_cq = [('Flag Specific C', 'CQ Try C'), ('Try A', 'CQ Try A'),
-                      ('Try B', 'CQ Try B')]
+        try_and_cq = [('Try A', 'CQ Try A'), ('Try B', 'CQ Try B')]
         self.assertEqual(try_and_cq, builders.try_bots_with_cq_mirror())
 
     def test_all_port_names(self):
diff --git a/third_party/blink/tools/blinkpy/web_tests/fuzzy_diff_analyzer/fuzzy_diff_analyzer.py b/third_party/blink/tools/blinkpy/web_tests/fuzzy_diff_analyzer/fuzzy_diff_analyzer.py
index 3b0da5d..b2206e2 100644
--- a/third_party/blink/tools/blinkpy/web_tests/fuzzy_diff_analyzer/fuzzy_diff_analyzer.py
+++ b/third_party/blink/tools/blinkpy/web_tests/fuzzy_diff_analyzer/fuzzy_diff_analyzer.py
@@ -15,6 +15,7 @@
 """
 
 import argparse
+import re
 
 from blinkpy.web_tests.fuzzy_diff_analyzer import analyzer
 from blinkpy.web_tests.fuzzy_diff_analyzer import queries
@@ -51,6 +52,12 @@
         '--test-path',
         help='The test path that contains the tests to do fuzzy diff analyzer.'
     )
+    parser.add_argument(
+        '--check-bugs-only',
+        action='store_true',
+        default=False,
+        help='Only checks the image diff tests result on existing bugs in the'
+        ' LUCI analysis database.')
     args = parser.parse_args()
     return args
 
@@ -60,20 +67,40 @@
 
     querier_instance = queries.FuzzyDiffAnalyzerQuerier(
         args.sample_period, args.project)
-    query_results = querier_instance.get_failed_image_comparison_ci_tests(
-        args.test_path)
-
     results_processor = results.ResultProcessor()
-    aggregated_results = results_processor.aggregate_results(query_results)
-
     matching_analyzer = analyzer.FuzzyMatchingAnalyzer(
         args.image_diff_num_threshold, args.distinct_diff_num_threshold)
-    for test_name, test_data in aggregated_results.items():
-        test_analysis_result = matching_analyzer.run_analyzer(test_data)
-        if test_analysis_result.is_analyzed:
-            print('')
-            print('test_name: %s' % test_name)
-            print('test_result: %s' % test_analysis_result.analysis_result)
-            print('')
+
+    # Find all bug ids or save empty id if it does not check all bugs.
+    if args.check_bugs_only:
+        bugs_info = querier_instance.get_web_test_flaky_bugs()
+        bugs = {}
+        for bug in bugs_info:
+            test_path_list = [
+                re.sub('ninja://:blink_w(eb|pt)_tests/', '', test_id)
+                for test_id in bug['test_ids']
+            ]
+            bugs[bug['bug_id']] = test_path_list
+    else:
+        bugs = {'': [args.test_path]}
+
+    for bug_id, test_list in bugs.items():
+        for test_path in test_list:
+            query_results = (querier_instance.
+                             get_failed_image_comparison_ci_tests(test_path))
+            aggregated_results = results_processor.aggregate_results(
+                query_results)
+
+            for test_name, test_data in aggregated_results.items():
+                test_analysis_result = matching_analyzer.run_analyzer(
+                    test_data)
+                if test_analysis_result.is_analyzed:
+                    print('')
+                    if bug_id:
+                        print('bug number: %s' % bug_id)
+                    print('test_name: %s' % test_name)
+                    print('test_result: %s' %
+                          test_analysis_result.analysis_result)
+                    print('')
 
     return 0
diff --git a/third_party/blink/tools/blinkpy/wpt_tests/test_loader.py b/third_party/blink/tools/blinkpy/wpt_tests/test_loader.py
index 0a52ea93..05d7406 100644
--- a/third_party/blink/tools/blinkpy/wpt_tests/test_loader.py
+++ b/third_party/blink/tools/blinkpy/wpt_tests/test_loader.py
@@ -96,7 +96,7 @@
             # A test file may be split between skipped and non-skipped variants.
             # Since `WPTAdapter` should never pass skipped tests to wptrunner,
             # there's no need to create their expectations here.
-            if exp_line.results == {ResultType.Skip}:
+            if ResultType.Skip in exp_line.results:
                 continue
             if exp_line.results == {ResultType.Pass} and not testharness_lines:
                 continue
diff --git a/third_party/blink/tools/blinkpy/wpt_tests/test_loader_unittest.py b/third_party/blink/tools/blinkpy/wpt_tests/test_loader_unittest.py
index 1a57838b..8abecba2 100644
--- a/third_party/blink/tools/blinkpy/wpt_tests/test_loader_unittest.py
+++ b/third_party/blink/tools/blinkpy/wpt_tests/test_loader_unittest.py
@@ -153,6 +153,21 @@
         self.assertEqual(subtest.get('expected-fail-message'),
                          'promise_rejects_dom: message\n  3')
 
+    def test_load_variant_one_skipped(self):
+        self.fs.write_text_file(
+            self.finder.path_from_web_tests('TestExpectations'),
+            textwrap.dedent("""\
+                # results: [ Failure Skip ]
+                external/wpt/variant.html?foo=bar/abc [ Failure ]
+                external/wpt/variant.html?foo=baz [ Failure Skip ]
+                """))
+        test_file = self._load_metadata('variant.html')
+        test = test_file.get_test('variant.html?foo=bar/abc')
+        self.assertEqual(test.expected, 'OK')
+        self.assertEqual(test.known_intermittent,
+                         ['ERROR', 'PRECONDITION_FAILED'])
+        self.assertIsNone(test_file.get_test('variant.html?foo=baz'))
+
     def test_load_baseline_precondition_failed(self):
         self.fs.write_text_file(
             self.finder.path_from_web_tests(
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index 3175e950..7f55ea03 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -1,4 +1,4 @@
-# tags: [ Android Fuchsia Linux Mac Mac10.15 Mac11 Mac11-arm64 Mac12 Mac12-arm64 Mac13 Mac13-arm64 Win Win10.20h2 Win11 Win11-arm64 ]
+# tags: [ Android Chrome Fuchsia Linux Mac Mac10.15 Mac11 Mac11-arm64 Mac12 Mac12-arm64 Mac13 Mac13-arm64 Win Win10.20h2 Win11 Win11-arm64 ]
 # tags: [ Release Debug ]
 # results: [ Skip Pass ]
 
@@ -2071,3 +2071,18 @@
 # Linux due to resource constraints.
 [ Mac ] external/wpt/webdriver/tests/* [ Skip ]
 [ Win ] external/wpt/webdriver/tests/* [ Skip ]
+
+# Bluetooth tests do not work on Chrome
+[ Chrome ] external/wpt/bluetooth/* [ Skip ]
+[ Chrome ] wpt_internal/bluetooth/* [ Skip ]
+[ Chrome ] external/wpt/fledge/* [ Skip ]
+[ Chrome ] external/wpt/speculation-rules/prerender/* [ Skip ]
+[ Chrome ] external/wpt/speculation-rules/prerender/credentialed-prerender-not-opt-in.html [ Pass ]
+[ Chrome ] external/wpt/speculation-rules/prerender/csp-script-src-self.html [ Pass ]
+[ Chrome ] external/wpt/speculation-rules/prerender/referrer-policy-from-rules.html?2-last [ Pass ]
+[ Chrome ] external/wpt/speculation-rules/prerender/remove-script-element.html [ Pass ]
+[ Chrome ] external/wpt/speculation-rules/prerender/response-code-non-successful.html?code=204 [ Pass ]
+[ Chrome ] external/wpt/speculation-rules/prerender/response-code-non-successful.html?code=205 [ Pass ]
+[ Chrome ] external/wpt/speculation-rules/prerender/response-code-non-successful.html?code=402 [ Pass ]
+[ Chrome ] external/wpt/speculation-rules/prerender/response-code-non-successful.html?code=500 [ Pass ]
+[ Chrome ] external/wpt/speculation-rules/prerender/response-code-successful.html?code=202 [ Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 866becb..25cf2be6 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1,4 +1,4 @@
-# tags: [ Fuchsia Linux Mac Mac10.15 Mac11 Mac11-arm64 Mac12 Mac12-arm64 Mac13 Mac13-arm64 Win Win10.20h2 Win11 Win11-arm64 iOS16-simulator]
+# tags: [ Chrome Fuchsia Linux Mac Mac10.15 Mac11 Mac11-arm64 Mac12 Mac12-arm64 Mac13 Mac13-arm64 Win Win10.20h2 Win11 Win11-arm64 iOS16-simulator]
 # tags: [ Release Debug ]
 # results: [ Timeout Crash Pass Failure Skip ]
 
@@ -430,7 +430,9 @@
 
 # This test has a bug in it that prevents it from being able to deal with order
 # differences it claims to support.
-crbug.com/1076129 external/wpt/service-workers/service-worker/clients-matchall-frozen.https.html [ Failure Pass ]
+crbug.com/1076129 [ Win ] external/wpt/service-workers/service-worker/clients-matchall-frozen.https.html [ Failure Pass ]
+crbug.com/1076129 [ Mac ] external/wpt/service-workers/service-worker/clients-matchall-frozen.https.html [ Failure Pass ]
+crbug.com/1076129 [ Linux ] external/wpt/service-workers/service-worker/clients-matchall-frozen.https.html [ Failure Pass ]
 
 # Flakily timing out or failing.
 # TODO(ccameron): Investigate this.
@@ -4204,7 +4206,9 @@
 # Sheriff 2019-07-04
 crbug.com/981267 http/tests/devtools/persistence/persistence-move-breakpoints-on-reload.js [ Failure Pass Timeout ]
 # TODO(crbug.com/980588): reenable once WPT is fixed
-crbug.com/980588 external/wpt/screen-orientation/lock-unlock-check.html [ Failure Pass ]
+crbug.com/980588 [ Win ] external/wpt/screen-orientation/lock-unlock-check.html [ Failure Pass ]
+crbug.com/980588 [ Mac ] external/wpt/screen-orientation/lock-unlock-check.html [ Failure Pass ]
+crbug.com/980588 [ Linux ] external/wpt/screen-orientation/lock-unlock-check.html [ Failure Pass ]
 
 # WebRTC tests that fails (by timing out) because `getSynchronizationSources()`
 # on the audio side needs a hardware sink for the returned dictionary entries to
@@ -4478,8 +4482,12 @@
 crbug.com/1249043 external/wpt/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html [ Failure Pass ]
 crbug.com/1287036 external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html [ Skip Timeout ]
 crbug.com/1287036 virtual/plz-dedicated-worker/external/wpt/html/cross-origin-embedder-policy/multi-globals/workers-coep-report.https.html [ Failure Pass ]
-crbug.com/1265587 external/wpt/html/user-activation/activation-trigger-pointerevent.html?pen [ Failure ]
-crbug.com/1270351 external/wpt/html/user-activation/activation-trigger-pointerevent.html?touch [ Failure ]
+crbug.com/1265587 [ Win ] external/wpt/html/user-activation/activation-trigger-pointerevent.html?pen [ Failure ]
+crbug.com/1265587 [ Mac ] external/wpt/html/user-activation/activation-trigger-pointerevent.html?pen [ Failure ]
+crbug.com/1265587 [ Linux ] external/wpt/html/user-activation/activation-trigger-pointerevent.html?pen [ Failure ]
+crbug.com/1270351 [ Win ] external/wpt/html/user-activation/activation-trigger-pointerevent.html?touch [ Failure ]
+crbug.com/1270351 [ Mac ] external/wpt/html/user-activation/activation-trigger-pointerevent.html?touch [ Failure ]
+crbug.com/1270351 [ Linux ] external/wpt/html/user-activation/activation-trigger-pointerevent.html?touch [ Failure ]
 crbug.com/1159661 external/wpt/html/interaction/focus/document-level-focus-apis/document-has-system-focus.html [ Timeout ]
 crbug.com/1317079 external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-failure.https.html [ Timeout ]
 crbug.com/1317079 external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.https.html [ Timeout ]
@@ -5293,7 +5301,6 @@
 crbug.com/1276201 [ Mac ] external/wpt/html/browsers/the-window-object/open-close/open-features-tokenization-top-left.html [ Crash Failure Pass Timeout ]
 crbug.com/1275967 [ Debug Linux ] external/wpt/permissions-policy/permissions-policy-frame-policy-timing.https.sub.html [ Failure Pass ]
 crbug.com/1276207 virtual/gpu-rasterization/images/color-profile-image-object-fit.html [ Failure Pass ]
-crbug.com/1276290 [ Mac ] wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker.html [ Crash Failure Pass Timeout ]
 
 crbug.com/1159463 crbug.com/1278570 [ Linux ] virtual/gpu-rasterization/images/directly-composited-image-orientation.html [ Failure Pass ]
 crbug.com/1159463 crbug.com/1278570 [ Mac11 ] virtual/gpu-rasterization/images/directly-composited-image-orientation.html [ Failure Pass ]
@@ -5785,7 +5792,9 @@
 crbug.com/1454956 [ Mac ] virtual/gpu/external/wpt/mediacapture-record/MediaRecorder-canvas-media-source.https.html [ Failure ]
 crbug.com/1345886 [ Linux ] plugins/user-gesture.html [ Failure ]
 crbug.com/1464848 [ Mac10.15 ] http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ]
-crbug.com/1466578 external/wpt/event-timing/event-click-visibilitychange.html [ Failure Pass ]
+crbug.com/1466578 [ Win ] external/wpt/event-timing/event-click-visibilitychange.html [ Failure Pass ]
+crbug.com/1466578 [ Mac ] external/wpt/event-timing/event-click-visibilitychange.html [ Failure Pass ]
+crbug.com/1466578 [ Linux ] external/wpt/event-timing/event-click-visibilitychange.html [ Failure Pass ]
 crbug.com/1446711 [ Mac ] media/controls/playback-speed-menu.html [ Timeout ]
 crbug.com/1446711 [ Win ] virtual/media-foundation-for-clear-dcomp/media/controls/accessibility-playback-speed-button.html [ Timeout ]
 crbug.com/1426680 [ Mac13-arm64 ] fast/canvas/OffscreenCanvas-copyImage.html [ Timeout ]
@@ -6384,7 +6393,9 @@
 # Sheriff 2023-01-23
 crbug.com/1409463 external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-screeny.html [ Crash Failure Pass Timeout ]
 
-external/wpt/permissions-policy/payment-extension-allowed-by-permissions-policy-attribute.https.sub.html [ Failure ]
+[ Win ] external/wpt/permissions-policy/payment-extension-allowed-by-permissions-policy-attribute.https.sub.html [ Failure ]
+[ Mac ] external/wpt/permissions-policy/payment-extension-allowed-by-permissions-policy-attribute.https.sub.html [ Failure ]
+[ Linux ] external/wpt/permissions-policy/payment-extension-allowed-by-permissions-policy-attribute.https.sub.html [ Failure ]
 
 # Sheriff 2023-01-27
 crbug.com/1289550 fast/block/float/4145535-crash.html [ Failure Pass ]
@@ -6783,7 +6794,9 @@
 crbug.com/1459347 [ Fuchsia ] paint/invalidation/shadow-multiple.html [ Failure Pass ]
 
 # Remove when crbug.com/1453780 is fixed
-crbug.com/1453780 external/wpt/infrastructure/testdriver/test_win_open_with_interaction.html [ Failure Pass ]
+crbug.com/1453780 [ Win ] external/wpt/infrastructure/testdriver/test_win_open_with_interaction.html [ Failure Pass ]
+crbug.com/1453780 [ Mac ] external/wpt/infrastructure/testdriver/test_win_open_with_interaction.html [ Failure Pass ]
+crbug.com/1453780 [ Linux ] external/wpt/infrastructure/testdriver/test_win_open_with_interaction.html [ Failure Pass ]
 
 # Temporarily disable test to land frontend color and margin changes
 crbug.com/1456690 http/tests/devtools/console/console-viewport-control.js [ Failure Pass ]
@@ -7041,6 +7054,369 @@
 crbug.com/432153 virtual/css-masking-disabled/external/wpt/css/css-masking/animations/mask-position-interpolation.html [ Failure ]
 crbug.com/432153 virtual/css-masking-disabled/external/wpt/css/css-masking/parsing/mask-position-valid.html [ Failure ]
 
+# Chrome specific failures
+crbug.com/1499775 [ Chrome ] external/wpt/accessibility/crashtests/svg-mouse-listener.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/attribution-reporting/request-format.sub.https.html?method=fetch&eligible={"eventSourceEligible":true,"triggerEligible":false}&expected-eligible=event-source [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/attribution-reporting/request-format.sub.https.html?method=xhr&eligible={"eventSourceEligible":true,"triggerEligible":false}&expected-eligible=event-source [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/background-fetch/abort.https.window.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/background-fetch/fetch-uploads.https.window.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/background-fetch/fetch.https.window.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/background-fetch/match.https.window.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/background-fetch/update-ui.https.window.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/compat/webkit-box-rtl-flex.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/content-security-policy/inheritance/blob-inherits-from-meta-http-equiv-with-invalid-characters.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-abort.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-after-abort.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-auto-selected-flag.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-basic.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-client-metadata-not-cached.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-cross-origin-policy.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-domainhint.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-endpoint-redirects.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-error-basic.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-iframe.https.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-loginhint.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-manifest-not-in-list.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-no-login-url.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-nonce-is-optional.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-not-observed-by-service-worker.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-pending-call-rejected.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-returning-account-auto-reauthn.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-revoke.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-store.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/credential-management/fedcm-token-returned-with-http-error.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/floats/float-nowrap-2.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/linebox/inline-formatting-context-003.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/linebox/inline-formatting-context-004.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/linebox/inline-formatting-context-005.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/linebox/inline-formatting-context-006.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/linebox/inline-formatting-context-007.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/linebox/vertical-align-sub-001.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/linebox/vertical-align-super-001.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/tables/anonymous-table-box-width-001.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/tables/table-anonymous-objects-087.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/tables/table-anonymous-objects-088.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/tables/table-anonymous-objects-089.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/tables/table-anonymous-objects-090.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/tables/table-anonymous-objects-091.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/tables/table-anonymous-objects-092.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/text/bidi-span-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/text/text-decoration-va-length-002.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/text/text-transform-bicameral-017.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/text/text-transform-bicameral-018.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/text/text-transform-bicameral-019.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/text/text-transform-bicameral-020.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/text/text-transform-bicameral-021.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/CSS2/text/text-transform-bicameral-022.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-blended-with-transform-and-perspective.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-both-parent-and-blended-with-3D-transform.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-canvas-parent.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-canvas-sibling.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-iframe-parent.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-iframe-sibling.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-with-transform-and-preserve-3D.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-backgrounds/background-clip/clip-text-flex.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-color/composited-filters-under-opacity.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-color/filters-under-will-change-opacity.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-contain/contain-layout-ink-overflow-019.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-contain/contain-layout-overflow-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-counter-styles/korean-hangul-formal/counter-korean-hangul-formal.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-counter-styles/korean-hanja-formal/counter-korean-hanja-formal.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-counter-styles/simp-chinese-informal/counter-simp-chinese-informal.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-counter-styles/trad-chinese-informal/counter-trad-chinese-informal.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-display/display-contents-before-after-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-display/display-contents-before-after-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-display/display-contents-before-after-003.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-display/display-contents-button.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-display/display-contents-details.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-display/display-contents-fieldset.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-display/display-contents-shadow-dom-1.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-display/display-contents-td-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-display/display-contents-unusual-html-elements-none.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-fonts/font-display/font-display-change.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-fonts/font-display/font-display-preload.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-fonts/font-display/font-display.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-fonts/font-variant-emoji-1.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-fonts/font-variant-ligatures-11.optional.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-fonts/font-variant-position-04.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-fonts/quoted-generic-ignored.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-fonts/size-adjust-01.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-fonts/size-adjust-unicode-range-system-fallback.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-tall.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-rtl.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-inline/initial-letter/initial-letter-float-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-inline/text-box-trim/text-box-trim-half-leading-inline-box-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-lists/content-property/marker-text-matches-lower-greek.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-masking/clip-path/clip-path-inline-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-masking/clip-path/clip-path-inline-004.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-masking/clip-path/clip-path-inline-010.html [ Failure ] # pass on wpt.fyi
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-masking/mask-image/mask-opacity-1e.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-multicol/multicol-fill-auto-block-children-002.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-multicol/multicol-width-ch-001.xht [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-overflow/scrollbar-gutter-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-overflow/scrollbar-gutter-vertical-rl-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-overflow/webkit-line-clamp-024.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-overflow/webkit-line-clamp-025.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-overflow/webkit-line-clamp-036.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-pseudo/first-letter-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-pseudo/first-letter-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-pseudo/first-letter-003.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-pseudo/first-line-with-inline-block.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-pseudo/highlight-cascade-008.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-pseudo/highlight-currentcolor-painting-properties-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-pseudo/highlight-currentcolor-painting-properties-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-pseudo/highlight-painting-003.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-pseudo/highlight-painting-004.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-ruby/block-ruby-003.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-decoration-subelements-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-color-property-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-color-property-001a.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-color-property-001b.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-color-property-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-position-property-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-position-property-001a.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-position-property-001b.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-position-property-001c.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-property-003.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-property-003b.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-property-004.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-property-004a.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-style-property-012.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-style-property-012a.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-style-property-012b.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-style-property-016.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text-decor/text-emphasis-style-property-016a.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/hyphens/hyphenate-limit-chars-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/hyphens/hyphens-auto-003.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/hyphens/hyphens-auto-004.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/hyphens/hyphens-auto-005.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/hyphens/hyphens-auto-010.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/hyphens/hyphens-auto-control.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/hyphens/hyphens-auto-inline-010.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/hyphens/hyphens-auto-last-word-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/hyphens/hyphens-character.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/hyphens/hyphens-punctuation-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/i18n/css3-text-line-break-opclns-201.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/letter-spacing/letter-spacing-bengali-yaphala-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/line-break/line-break-normal-hyphens-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/line-break/line-break-strict-hyphens-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/text-transform/text-transform-capitalize-034.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/white-space/pre-wrap-018.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/white-space/trailing-space-and-text-alignment-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/white-space/trailing-space-and-text-alignment-004.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/white-space/trailing-space-and-text-alignment-rtl-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/white-space/trailing-space-and-text-alignment-rtl-004.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/white-space/white-space-pre-wrap-justify-004.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/word-break/word-break-break-all-005.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/word-break/word-break-break-all-032.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/word-break/word-break-keep-all-006.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/word-break/word-break-normal-bo-000.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/word-break/word-break-normal-hi-000.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-text/word-break/word-break-normal-lo-000.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-transforms/backface-visibility-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-transforms/backface-visibility-hidden-animated-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-transforms/ttwf-css-3d-polygon-cycle.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-ui/compute-kind-widget-no-fallback-props-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-ui/text-overflow-027.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-ui/text-overflow-028.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/css-will-change/will-change-transform-zero-size-child-overflow-visible.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/filter-effects/backdrop-filter-fixed-clip.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/filter-effects/backdrop-filter-isolation.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/filter-effects/backdrop-filter-plus-filter.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/filter-effects/backdrop-filter-reference-filter.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/filter-effects/css-filters-animation-opacity.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/printing/monolithic-overflow-024-print.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/printing/monolithic-overflow-025-print.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/printing/page-margin-001-print.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/printing/page-margin-002-print.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/printing/page-margin-003-print.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/printing/page-size-001-print.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/printing/page-size-002-print.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/printing/page-size-006-print.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/selectors/dir-style-01a.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/selectors/dir-style-01b.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/css/selectors/invalidation/fullscreen-pseudo-class-in-has.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/css/selectors/invalidation/modal-pseudo-class-in-has.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/css/selectors/modal-pseudo-class.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/dom/events/scrolling/input-text-scroll-event-when-using-arrow-keys.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/event-timing/event-click-visibilitychange.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/eventsource/eventsource-request-cancellation.window.any.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/eventsource/eventsource-request-cancellation.window.any.worker.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/eventsource/request-credentials.window.any.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/fetch/api/abort/serviceworker-intercepted.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fetch/stale-while-revalidate/fetch.any.serviceworker.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/element-request-fullscreen-non-top.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/element-request-fullscreen-options.tentative.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/element-request-fullscreen-same-element.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/element-request-fullscreen-same.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/element-request-fullscreen-screen-size.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/element-request-fullscreen-svg-svg.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/element-request-fullscreen-timing.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/element-request-fullscreen-top.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/element-request-fullscreen-twice.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/element-request-fullscreen-two-elements.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/element-request-fullscreen.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/fullscreen-display-contents.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/fullscreen-reordering.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/promises-resolve.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/api/shadowroot-fullscreen-element.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/model/remove-last.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/model/remove-parent.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/model/remove-single.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/rendering/fullscreen-css-invalidation.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/rendering/fullscreen-css-transition.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/rendering/fullscreen-pseudo-class.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/rendering/fullscreen-root-block-scroll.html [ Timeout ] # pass on wpt.fyi
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/rendering/fullscreen-root-block-size.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/fullscreen/rendering/ua-style-iframe.html [ Timeout ] # pass on wpt.fyi
+crbug.com/1499775 [ Chrome ] external/wpt/html/browsers/browsing-the-web/navigating-across-documents/cross-origin-top-navigation-with-user-activation-in-parent.window.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/canvas/element/text/direction-inherit-rtl.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/canvas/element/text/direction-rtl.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/capability-delegation/delegate-fullscreen-request-popup-cross-origin.https.sub.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/capability-delegation/delegate-fullscreen-request-popup-same-origin.https.tentative.html [ Timeout ] # pass on wpt.fyi
+crbug.com/1499775 [ Chrome ] external/wpt/html/capability-delegation/delegate-fullscreen-request-subframe-cross-origin.https.sub.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/capability-delegation/delegate-fullscreen-request-subframe-same-origin.https.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-embedder-policy/reporting-to-document-reporting-endpoint.https.window.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-to-unsafe-none.https.html?5-6 [ Failure ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro_cross-origin.https.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro_cross-origin.https.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro.https.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro_cross-origin.https.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-blur.https.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-top.https.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-same-origin-allow-popups.https.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html?5-6 [ Crash Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html?7-8 [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html?7-8 [ Crash Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-002b.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-002c.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006a.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006b.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-006c.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009a.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009b.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/dir-isolation-009c.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-004.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-005.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-overflow.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-inline-alt.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/semantics/embedded-content/the-img-element/image-compositing-change.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/semantics/embedded-content/the-object-element/object-events.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/semantics/forms/the-selectlist-element/selectlist-explicit-size.tentative.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/semantics/interactive-elements/the-dialog-element/top-layer-stacking.tentative.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/semantics/popovers/popover-open-overflow-display.tentative.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/html/semantics/popovers/popover-top-layer-combinations.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/semantics/popovers/popover-top-layer-interactions.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/user-activation/activation-trigger-keyboard-enter.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/user-activation/activation-trigger-mouse-left.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/user-activation/activation-trigger-mouse-right.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/user-activation/activation-trigger-pointerevent.html?mouse [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/user-activation/activation-trigger-pointerevent.html?pen [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/user-activation/activation-trigger-pointerevent.html?touch [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/user-activation/propagation-same-and-cross-origin.sub.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/html/webappapis/scripting/event-loops/fully_active_document.window.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/infrastructure/assumptions/ahem.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/infrastructure/testdriver/test_win_open_with_interaction.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/long-animation-frame/tentative/loaf-first-ui-event.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/mathml/relations/css-styling/mozilla-393760-2.xml [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/mathml/relations/html5-tree/tabindex-002.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/notifications/event-onclose.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/notifications/event-onshow.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/notifications/getnotifications-across-processes.https.window.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/page-visibility/visibility-state-entry.tentative.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/performance-timeline/back-forward-cache-restoration.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/permissions-policy/payment-extension-allowed-by-permissions-policy-attribute.https.sub.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/permissions-policy/reporting/fullscreen-report-only.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/permissions-policy/reporting/report-only-and-enforce.https.sub.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/permissions-policy/reporting/report-only-single-endpoint.https.sub.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/permissions-policy/reporting/report-to-multiple-endpoints.https.sub.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/permissions-policy/reporting/report-to-single-endpoint.https.sub.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/pointerevents/pointerevent_contextmenu_is_a_pointerevent.html?touch [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/screen-orientation/event-before-promise.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/screen-orientation/fullscreen-interactions.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/screen-orientation/lock-basic.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/screen-orientation/lock-sandboxed-iframe.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/screen-orientation/lock-unlock-check.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/screen-orientation/nested-documents.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/screen-orientation/onchange-event.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/screen-orientation/unlock.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/screen-wake-lock/chrome-bug-1348019.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/scroll-animations/scroll-timelines/layout-changes-on-percentage-based-timeline.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/service-workers/service-worker/clients-matchall-frozen.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/signed-exchange/reporting/sxg-reporting-prefetch-invalid_integrity_header.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/signed-exchange/reporting/sxg-reporting-prefetch-mi_error.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/signed-exchange/reporting/sxg-reporting-prefetch-ok.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/signed-exchange/reporting/sxg-reporting-prefetch-parse_error.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/signed-exchange/reporting/sxg-reporting-prefetch-signature_verification_error-downgraded.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/signed-exchange/reporting/sxg-reporting-prefetch-signature_verification_error.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative.html [ Timeout ] # fail on wpt.fyi
+crbug.com/1499775 [ Chrome ] external/wpt/soft-navigation-heuristics/keydown.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/soft-navigation-heuristics/keypress.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/speculation-rules/prerender/response-code-successful.html?code=202 [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] external/wpt/storage-access-api/storage-access-permission.sub.https.window.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/svg/text/reftests/lang-attribute.svg [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/svg/text/reftests/xml-lang-attribute.svg [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] external/wpt/webrtc-stats/hardware-capability-stats.https.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/websockets/send-many-64K-messages-with-backpressure.any.sharedworker.html?wpt_flags=h2 [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/websockets/stream/tentative/backpressure-send.any.sharedworker.html?wpt_flags=h2 [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/webxr/dom-overlay/ar_dom_overlay.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/webxr/dom-overlay/ar_dom_overlay_hit_test.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] external/wpt/webxr/dom-overlay/nested_fullscreen.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/credential-management/fedcm-mismatch-dialog.tentative.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/credential-management/fedcm-reauth-with-signin-status.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-borders/subpixel-border-width-when-zoom-changes.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-fonts/default-monospace-family-mac.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-fonts/font-glyph-synthesis-mac.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-fonts/font-size-ex-ch-with-zoom.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-fonts/generic-families/font-family-cursive.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-fonts/generic-families/font-family-fantasy.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-fonts/generic-families/font-family-math.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-fonts/generic-families/font-family-monospace.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-fonts/generic-families/font-family-sans-serif.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-fonts/generic-families/font-family-serif.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-fonts/generic-families/font-family-standard.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-fonts/size-adjust-ex-zoom.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-lists/before-after-selectors-on-code-element.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-masking/mask-clip-text-not-supported.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-overflow/scrollbar-gutter-background-paint.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-overflow/scrollbar-gutter-content-overflowing.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-pseudo/grammar-error-color-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-pseudo/spelling-error-color-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-text-decor/text-decoration-line-grammar-error-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-text-decor/text-decoration-line-grammar-error-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-text-decor/text-decoration-line-spelling-error-001.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/css/css-text-decor/text-decoration-line-spelling-error-002.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/display-lock/css-content-visibility/content-visibility-event-sender-001.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/geolocation-api/watchPosition-page-visibility.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/hid/requestDevice/sandboxed_iframe.https.window.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/infrastructure/printing-reftest-pages.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/infrastructure/printing-set-size.html [ Failure ]  # Reftest image failure
+crbug.com/1499775 [ Chrome ] wpt_internal/prerender/restriction-speech-recognition.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/prerender/restriction-storage-estimate.https.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/prerender/restriction-web-audio.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/prerender/session-storage.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/presentation/presentation-controller-close-connection.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/presentation/presentation-controller-connection-closed-by-receiver.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/presentation/presentation-controller-terminate-connection.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/presentation/presentation-receiver-terminate-connection.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/presentation/presentation-reconnect.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/presentation/presentation-start-error.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/presentation/presentation-start.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/presentation/presentationconnectionavailableevent-ctor-mock.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/soft-navigation-heuristics/browser-initiated-popstate.tentative.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/speech/scripted/speechrecognition-restart-onend.html [ Skip Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/storage-access-api/storage-access-origin-trial.sub.https.window.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/webmidi/loopback-receive.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/webmidi/loopback-with-timestamp.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/webmidi/requestmidiaccess-upgrade.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/websocket-cookies/third-party-cookie-blocked.https.html [ Failure ]  # Flaky output
+crbug.com/1499775 [ Chrome ] wpt_internal/webusb/usbDevice-iframe.https.html [ Timeout ]
+crbug.com/1499775 [ Chrome ] wpt_internal/webxr/ar/iframe-oopif.sub.https.html [ Timeout ]
+
 # Gardener 2023-10-17
 crbug.com/1493342 [ Mac10.15 ] external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-video.html [ Failure ]
 crbug.com/1493342 [ Mac10.15 ] external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-video.html [ Failure ]
@@ -7070,3 +7446,12 @@
 # Gardener 2023-11-02
 crbug.com/1498203 external/wpt/fetch/fetch-later/send-on-discard.tentative.https.window.html [ Failure Pass ]
 crbug.com/1498203 virtual/keepalive-in-browser-migration/external/wpt/fetch/fetch-later/send-on-discard.tentative.https.window.html [ Failure Pass ]
+
+# Importer 2023-11-06
+crbug.com/626703 external/wpt/css/css-page/parsing/size-invalid.html [ Failure Pass ]
+crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justify-tabs-001.html [ Failure Pass ]
+crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justify-tabs-002.html [ Failure Pass ]
+crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justify-tabs-003.html [ Failure Pass ]
+crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justify-tabs-004.html [ Failure Pass ]
+crbug.com/626703 external/wpt/editing/run/formatblock.html?1-1000 [ Failure Pass ]
+crbug.com/626703 external/wpt/editing/run/formatblock.html?4001-last [ Failure Pass ]
\ No newline at end of file
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index d2353ed9..f739a10 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -710,7 +710,10 @@
       "external/wpt/navigation-api/navigate-event/cross-window/open-crossdocument-crossorigin-sameorigindomain.sub.html",
       "external/wpt/navigation-api/navigate-event/cross-window/open-samedocument-crossorigin-sameorigindomain.sub.html",
       "external/wpt/navigation-api/navigate-event/cross-window/submit-crossdocument-crossorigin-sameorigindomain.sub.html",
-      "external/wpt/navigation-api/navigate-event/cross-window/submit-samedocument-crossorigin-sameorigindomain.sub.html"
+      "external/wpt/navigation-api/navigate-event/cross-window/submit-samedocument-crossorigin-sameorigindomain.sub.html",
+      "external/wpt/longtask-timing/longtask-in-childiframe-crossorigin.html",
+      "external/wpt/longtask-timing/longtask-in-sibling-iframe-crossorigin.html",
+      "http/tests/security/drag-drop-same-unique-origin.html"
     ],
     "exclusive_tests": "ALL",
     "args": ["--disable-site-isolation-trials",
@@ -1652,7 +1655,7 @@
       "--enable-features=InterestGroupStorage,PrivacySandboxAdsAPIsOverride,FencedFrames:implementation_type/mparch,FledgeRounding:fledge_bid_reporting_bits/8/fledge_score_reporting_bits/8/fledge_ad_cost_reporting_bits/8",
       "--disable-threaded-compositing", "--disable-threaded-animation"
     ],
-    "expires": "Dec 1, 2023"
+    "expires": "Sep 1, 2024"
   },
   {
     "prefix": "automatic-lazy-frame-loading",
diff --git a/third_party/blink/web_tests/accessibility/computed-name-expected.txt b/third_party/blink/web_tests/accessibility/computed-name-expected.txt
index b811fbe7..6f82cb7 100644
--- a/third_party/blink/web_tests/accessibility/computed-name-expected.txt
+++ b/third_party/blink/web_tests/accessibility/computed-name-expected.txt
@@ -51,7 +51,6 @@
 PASS implicitRoleElement.computedName is "implicit list name"
 PASS name is "listbox name"
 PASS implicitRoleElement.computedName is "implicit listbox name"
-PASS name is "option name"
 PASS name is "log name"
 PASS name is "main name"
 PASS implicitRoleElement.computedName is "implicit main name"
@@ -71,6 +70,7 @@
 PASS implicitRoleElement.computedName is "implicit navigation name"
 PASS name is "note name"
 PASS name is "option name"
+PASS name is "option name"
 PASS name is "progressbar name"
 PASS implicitRoleElement.computedName is "implicit progressbar name"
 PASS name is "radio name"
diff --git a/third_party/blink/web_tests/accessibility/computed-name.html b/third_party/blink/web_tests/accessibility/computed-name.html
index 1a795e7..a0154f3 100644
--- a/third_party/blink/web_tests/accessibility/computed-name.html
+++ b/third_party/blink/web_tests/accessibility/computed-name.html
@@ -97,9 +97,7 @@
       <ul data-role="list" aria-label="implicit list name"><li data-role="listitem">implicit listitem name</li></ul>
       <ol data-role="list" aria-label="implicit list name"><li data-role="listitem">implicit listitem name</li></ol>
 
-      <div role="listbox" aria-label="listbox name">
-        <div role="option">option name</div>
-      </div>
+      <div role="listbox" aria-label="listbox name">This is a listbox</div>
       <select data-role="listbox" size="1" aria-label="implicit listbox name">
         <option value="1">First option</option>
         <option value="2">Second</option>
@@ -138,6 +136,7 @@
 
       <div role="note" aria-label="note name">This is a note</div>
 
+      <div role="option">option name</div>
       <div role="option" aria-label="option name">This is an option</div>
       <select multiple>
         <option value="1" data-role="option" data-knownFailure>implicit option name</option>
diff --git a/third_party/blink/web_tests/accessibility/computed-role-expected.txt b/third_party/blink/web_tests/accessibility/computed-role-expected.txt
index dee8ad1..e6c932c 100644
--- a/third_party/blink/web_tests/accessibility/computed-role-expected.txt
+++ b/third_party/blink/web_tests/accessibility/computed-role-expected.txt
@@ -61,9 +61,6 @@
 PASS implicitRoleElement.computedRole is "list"
 PASS implicitRoleElement.computedRole is "list"
 PASS roleElement.computedRole is "listbox"
-PASS roleElement.computedRole is "option"
-PASS implicitRoleElement.computedRole is "option"
-PASS implicitRoleElement.computedRole is "option"
 PASS roleElement.computedRole is "log"
 PASS roleElement.computedRole is "main"
 PASS implicitRoleElement.computedRole is "main"
@@ -77,6 +74,9 @@
 PASS roleElement.computedRole is "note"
 PASS roleElement.computedRole is "navigation"
 PASS implicitRoleElement.computedRole is "navigation"
+PASS roleElement.computedRole is "option"
+PASS implicitRoleElement.computedRole is "option"
+PASS implicitRoleElement.computedRole is "option"
 PASS roleElement.computedRole is "none"
 PASS roleElement.computedRole is "progressbar"
 PASS implicitRoleElement.computedRole is "progressbar"
diff --git a/third_party/blink/web_tests/accessibility/computed-role.html b/third_party/blink/web_tests/accessibility/computed-role.html
index 8e33707..9e397052 100644
--- a/third_party/blink/web_tests/accessibility/computed-role.html
+++ b/third_party/blink/web_tests/accessibility/computed-role.html
@@ -108,9 +108,7 @@
       <ul data-role="list"><li data-role="listitem">This is a list item</li></ul>
       <ol data-role="list"><li data-role="listitem">This is a list item</li></ol>
 
-      <div role="listbox">
-        <div role="option">This is an option</div>
-      </div>
+      <div role="listbox">This is a listbox</div>
 
       <div role="log">This is a log</div>
 
@@ -141,6 +139,7 @@
       <div role="navigation">This is a navigation</div>
       <nav data-role="navigation">This is a navigation</nav>
 
+      <div role="option">This is an option</div>
       <select multiple>
         <option value="1" data-role="option">First option</option>
         <option value="2" data-role="option">Second</option>
diff --git a/third_party/blink/web_tests/accessibility/disabled-not-selectable.html b/third_party/blink/web_tests/accessibility/disabled-not-selectable.html
index 38b63ab0..0f04bca 100644
--- a/third_party/blink/web_tests/accessibility/disabled-not-selectable.html
+++ b/third_party/blink/web_tests/accessibility/disabled-not-selectable.html
@@ -4,9 +4,7 @@
 <script src="../resources/testharnessreport.js"></script>
 
 <div id="treeitem1" role="treeitem" tabindex="-1" aria-selected="false">X</div>
-<div role="listbox">
-  <div id="option1" role="option" tabindex="-1">X</div>
-</div>
+<div id="option1" role="option" tabindex="-1">X</div>
 <div id="tab1" role="tab" tabindex="-1">X</div>
 <div role="grid">
   <div id="gridcell1" role="gridcell" tabindex="-1" aria-selected="false">X</div>
@@ -14,9 +12,7 @@
 <div id="checkbox1" role="checkbox" tabindex="-1">X</div>
 
 <div id="treeitem2" role="treeitem" tabindex="-1" aria-selected="true">X</div>
-<div role="listbox">
-  <div id="option2" role="option" tabindex="-1" aria-selected="true">X</div>
-</div>
+<div id="option2" role="option" tabindex="-1" aria-selected="true">X</div>
 <div id="tab2" role="tab" tabindex="-1" aria-selected="true">X</div>
 <div role="grid">
   <div id="gridcell2" role="gridcell" tabindex="-1" aria-selected="true">X</div>
@@ -24,9 +20,7 @@
 <div id="checkbox2" role="checkbox" tabindex="-1" aria-selected="true">X</div>
 
 <div id="treeitem3" role="treeitem" tabindex="-1" aria-selected="true" aria-disabled="true">X</div>
-<div role="listbox">
-  <div id="option3" role="option" tabindex="-1" aria-selected="true" aria-disabled="true">X</div>
-</div>
+<div id="option3" role="option" tabindex="-1" aria-selected="true" aria-disabled="true">X</div>
 <div id="tab3" role="tab" tabindex="-1" aria-selected="true" aria-disabled="true">X</div>
 <div role="grid">
   <div id="gridcell3" role="gridcell" tabindex="-1" aria-selected="true" aria-disabled="true">X</div>
diff --git a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-logout-rps.https.html b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-logout-rps.https.html
deleted file mode 100644
index 51b1230..0000000
--- a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-logout-rps.https.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>IdentityCredential.logoutRPs() promise resolution</title>
-<link rel="author" title="Peter Kotwicz" href="mailto:pkotwicz@chromium.org">
-<link rel="help" href="https://wicg.github.io/FedCM/#browser-api-idp-sign-out">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<script type="module">
-  import {fedcm_mojo_mock_test} from './support/fedcm-mojojs-helper.js';
-
-  fedcm_mojo_mock_test(async (t, mock) => {
-    mock.logoutRpsReturn("kError");
-    return promise_rejects_dom(t, "NetworkError",
-      IdentityCredential.logoutRPs([{
-        accountId: "1234",
-        url: "https://rp.example/logout.php"
-      }])
-    );
-  }, "IdentityCredential.logoutRPs() error.");
-
-  fedcm_mojo_mock_test(async (t, mock) => {
-    mock.logoutRpsReturn("kSuccess");
-    await IdentityCredential.logoutRPs([{
-      accountId: "1234",
-      url: "https://rp.example/logout.php"
-    }]);
-  }, "IdentityCredential.logoutRPs() success.");
-
-  fedcm_mojo_mock_test(async (t, mock) => {
-    return promise_rejects_dom(t, "NetworkError",
-      IdentityCredential.logoutRPs([{
-        accountId: "1234",
-        url: "https://other-rp.example/logout.php"
-      }])
-    );
-  }, "Logout URL should honor Content-Security-Policy.");
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-logout-rps.https.html.headers b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-logout-rps.https.html.headers
deleted file mode 100644
index 90454dbb..0000000
--- a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-logout-rps.https.html.headers
+++ /dev/null
@@ -1 +0,0 @@
-Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; connect-src https://rp.example
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-local-network-access-target.https.html b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-private-network-access-target.https.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-local-network-access-target.https.html
rename to third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-private-network-access-target.https.html
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-local-network-access.https.html b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-private-network-access.https.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-local-network-access.https.html
rename to third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-private-network-access.https.html
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-local-network-access.https.html.headers b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-private-network-access.https.html.headers
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-local-network-access.https.html.headers
rename to third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/fenced-frame-private-network-access.https.html.headers
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/support.sub.js b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/support.sub.js
index 3d71b2d..0cb757c 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/support.sub.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/resources/support.sub.js
@@ -474,14 +474,14 @@
 async function fencedFrameTest(t, { source, target, expected }) {
   // Allows running tests in parallel.
   const target_url = preflightUrl(target);
-  target_url.searchParams.set("file", "fenced-frame-local-network-access-target.https.html");
+  target_url.searchParams.set("file", "fenced-frame-private-network-access-target.https.html");
   target_url.searchParams.set("is-loaded-in-fenced-frame", true);
 
   const frame_loaded_key = token();
   const child_frame_target = generateURL(target_url, [frame_loaded_key]);
 
   const source_url =
-      resolveUrl("resources/fenced-frame-local-network-access.https.html", sourceResolveOptions(source));
+      resolveUrl("resources/fenced-frame-private-network-access.https.html", sourceResolveOptions(source));
   source_url.searchParams.set("fenced_frame_url", child_frame_target);
 
   const urn = await generateURNFromFledge(source_url, []);
diff --git a/third_party/blink/web_tests/external/wpt/fledge/tentative/component-auction.https.window.js b/third_party/blink/web_tests/external/wpt/fledge/tentative/component-auction.https.window.js
new file mode 100644
index 0000000..83980541
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fledge/tentative/component-auction.https.window.js
@@ -0,0 +1,437 @@
+// META: script=/resources/testdriver.js
+// META: script=/common/utils.js
+// META: script=/common/subset-tests.js
+// META: script=resources/fledge-util.sub.js
+// META: timeout=long
+// META: variant=?1-5
+// META: variant=?6-10
+// META: variant=?11-last
+
+"use strict";
+
+// Creates an AuctionConfig with a single component auction.
+function createComponentAuctionConfig(uuid) {
+  let componentAuctionConfig = {
+    seller: window.location.origin,
+    decisionLogicURL: createDecisionScriptURL(uuid),
+    interestGroupBuyers: [window.location.origin]
+  };
+
+  return {
+    seller: window.location.origin,
+    decisionLogicURL: createDecisionScriptURL(uuid),
+    interestGroupBuyers: [],
+    componentAuctions: [componentAuctionConfig]
+  };
+}
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  await joinInterestGroup(
+      test, uuid,
+      { biddingLogicURL: createBiddingScriptURL()});
+
+  await runBasicFledgeTestExpectingNoWinner(test, uuid, createComponentAuctionConfig(uuid));
+}, 'Component auction allowed not specified by bidder.');
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  await joinInterestGroup(
+      test, uuid,
+      { biddingLogicURL: createBiddingScriptURL(
+        { allowComponentAuction: false })});
+
+  await runBasicFledgeTestExpectingNoWinner(test, uuid, createComponentAuctionConfig(uuid));
+}, 'Component auction not allowed by bidder.');
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  await joinInterestGroup(
+      test, uuid,
+      { biddingLogicURL: createBiddingScriptURL(
+        { allowComponentAuction: true })});
+
+  let auctionConfig = createComponentAuctionConfig(uuid);
+  auctionConfig.componentAuctions[0].decisionLogicURL = createDecisionScriptURL(
+      uuid,
+      { scoreAd: "return 5;" });
+
+  await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
+}, 'Component auction allowed not specified by component seller.');
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  await joinInterestGroup(
+      test, uuid,
+      { biddingLogicURL: createBiddingScriptURL(
+        { allowComponentAuction: true })});
+
+  let auctionConfig = createComponentAuctionConfig(uuid);
+  auctionConfig.componentAuctions[0].decisionLogicURL = createDecisionScriptURL(
+      uuid,
+      { scoreAd: "return {desirability: 5, allowComponentAuction: false};" });
+
+  await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
+}, 'Component auction not allowed by component seller.');
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  await joinInterestGroup(
+      test, uuid,
+      { biddingLogicURL: createBiddingScriptURL(
+        { allowComponentAuction: true })});
+
+  let auctionConfig = createComponentAuctionConfig(uuid);
+  auctionConfig.decisionLogicURL = createDecisionScriptURL(
+      uuid,
+      { scoreAd: "return 5;" });
+
+  await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
+}, 'Component auction allowed not specified by top-level seller.');
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  await joinInterestGroup(
+      test, uuid,
+      { biddingLogicURL: createBiddingScriptURL(
+        { allowComponentAuction: true })});
+
+  let auctionConfig = createComponentAuctionConfig(uuid);
+  auctionConfig.interestGroupBuyers = [window.location.origin];
+
+  try {
+    await runBasicFledgeAuction(test, uuid, auctionConfig);
+  } catch (exception) {
+    assert_true(exception instanceof TypeError, "did not get expected error: " + exception);
+    return;
+  }
+  throw 'Exception unexpectedly not thrown.'
+}, 'Component auction top-level auction cannot have buyers.');
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  await joinInterestGroup(
+      test, uuid,
+      { biddingLogicURL: createBiddingScriptURL(
+        { allowComponentAuction: true })});
+
+  let auctionConfig = createComponentAuctionConfig(uuid);
+  auctionConfig.decisionLogicURL = createDecisionScriptURL(
+      uuid,
+      { scoreAd: "return {desirability: 5, allowComponentAuction: false};" });
+
+  await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
+}, 'Component auction not allowed by top-level seller.');
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  // Use distinct origins so can validate all origin parameters passed to worklets.
+  let bidder = OTHER_ORIGIN1;
+  let componentSeller = OTHER_ORIGIN2;
+  let topLevelSeller = OTHER_ORIGIN3;
+
+  let bidderReportURL = createBidderReportURL(uuid);
+  let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/1);
+  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/2);
+
+  // Note that generateBid() and reportWin() receive slightly different
+  // "browserSignals" fields - only reportWin() gets "interestGroupOwner", so
+  // need different sets of checks for them.
+  await joinCrossOriginInterestGroup(
+      test, uuid, bidder,
+      { biddingLogicURL: createBiddingScriptURL(
+        { origin: bidder,
+          allowComponentAuction: true,
+          generateBid:
+            `if (browserSignals.seller !== "${componentSeller}")
+               throw "Unexpected seller: " + browserSignals.seller;
+             if (browserSignals.componentSeller !== undefined)
+               throw "Unexpected componentSeller: " + browserSignals.componentSeller;
+             if (browserSignals.topLevelSeller !== "${topLevelSeller}")
+               throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
+             if (browserSignals.interestGroupOwner !== undefined)
+               throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
+             if (browserSignals.topWindowHostname !== "${window.location.hostname}")
+               throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;`,
+          reportWin:
+            `if (browserSignals.seller !== "${componentSeller}")
+               throw "Unexpected seller: " + browserSignals.seller;
+             if (browserSignals.componentSeller !== undefined)
+               throw "Unexpected componentSeller: " + browserSignals.componentSeller;
+             if (browserSignals.topLevelSeller !== "${topLevelSeller}")
+               throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
+             if (browserSignals.interestGroupOwner !== "${bidder}")
+               throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
+             if (browserSignals.topWindowHostname !== "${window.location.hostname}")
+               throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;
+             sendReportTo("${bidderReportURL}");`})});
+
+  // Checks for scoreAd() and reportResult() for the component seller.
+  let componentSellerChecks =
+      `if (browserSignals.seller !== undefined)
+         throw "Unexpected seller: " + browserSignals.seller;
+       if (browserSignals.componentSeller !== undefined)
+         throw "Unexpected componentSeller: " + browserSignals.componentSeller;
+       if (browserSignals.topLevelSeller !== "${topLevelSeller}")
+         throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
+       if (browserSignals.interestGroupOwner !== "${bidder}")
+         throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
+       if (browserSignals.topWindowHostname !== "${window.location.hostname}")
+         throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;`;
+
+  let componentAuctionConfig = {
+    seller: componentSeller,
+    decisionLogicURL: createDecisionScriptURL(
+        uuid,
+        { origin: componentSeller,
+          scoreAd: componentSellerChecks,
+          reportResult: `${componentSellerChecks}
+                          sendReportTo("${componentSellerReportURL}");` }),
+    interestGroupBuyers: [bidder]
+  };
+
+  // Checks for scoreAd() and reportResult() for the top-level seller.
+  let topLevelSellerChecks =
+      `if (browserSignals.seller !== undefined)
+         throw "Unexpected seller: " + browserSignals.seller;
+       if (browserSignals.componentSeller !== "${componentSeller}")
+         throw "Unexpected componentSeller: " + browserSignals.componentSeller;
+       if (browserSignals.topLevelSeller !== undefined)
+         throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
+       if (browserSignals.interestGroupOwner !== "${bidder}")
+         throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
+       if (browserSignals.topWindowHostname !== "${window.location.hostname}")
+         throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;`;
+
+  let auctionConfigOverrides = {
+    seller: topLevelSeller,
+    decisionLogicURL: createDecisionScriptURL(
+        uuid,
+        { origin: topLevelSeller,
+          scoreAd: topLevelSellerChecks,
+          reportResult: `${topLevelSellerChecks}
+                         sendReportTo("${topLevelSellerReportURL}");` }),
+    interestGroupBuyers: [],
+    componentAuctions: [componentAuctionConfig]
+  };
+
+  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides);
+  await waitForObservedRequests(
+      uuid,
+      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
+}, 'Component auction browserSignals origins.');
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  let bidderReportURL = createBidderReportURL(uuid);
+  let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/1);
+  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/2);
+
+  await joinInterestGroup(
+      test, uuid,
+      { biddingLogicURL: createBiddingScriptURL(
+        { allowComponentAuction: true,
+          bid: 5,
+          reportWin:
+            `if (browserSignals.bid !== 5)
+               throw "Unexpected bid: " + browserSignals.bid;
+             sendReportTo("${bidderReportURL}");`})});
+
+  let auctionConfig = createComponentAuctionConfig(uuid);
+
+  auctionConfig.componentAuctions[0].decisionLogicURL =
+    createDecisionScriptURL(
+        uuid,
+        { scoreAd:
+              `if (bid !== 5)
+                 throw "Unexpected component bid: " + bid`,
+          reportResult:
+              `if (browserSignals.bid !== 5)
+                 throw "Unexpected component bid: " + browserSignals.bid;
+               if (browserSignals.modifiedBid !== undefined)
+                 throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
+               sendReportTo("${componentSellerReportURL}");` });
+
+  auctionConfig.decisionLogicURL =
+    createDecisionScriptURL(
+        uuid,
+        { scoreAd:
+              `if (bid !== 5)
+                 throw "Unexpected top-level bid: " + bid`,
+          reportResult:
+              `if (browserSignals.bid !== 5)
+                 throw "Unexpected top-level bid: " + browserSignals.bid;
+               if (browserSignals.modifiedBid !== undefined)
+                 throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
+               sendReportTo("${topLevelSellerReportURL}");` });
+
+  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
+  await waitForObservedRequests(
+      uuid,
+      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
+}, 'Component auction unmodified bid.');
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  let bidderReportURL = createBidderReportURL(uuid);
+  let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/1);
+  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/2);
+
+  await joinInterestGroup(
+      test, uuid,
+      { biddingLogicURL: createBiddingScriptURL(
+        { allowComponentAuction: true,
+          bid: 5,
+          reportWin:
+            `if (browserSignals.bid !== 5)
+               throw "Unexpected bid: " + browserSignals.bid;
+             sendReportTo("${bidderReportURL}");`})});
+
+  let auctionConfig = createComponentAuctionConfig(uuid);
+
+  auctionConfig.componentAuctions[0].decisionLogicURL =
+      createDecisionScriptURL(
+          uuid,
+          { scoreAd:
+                `if (bid !== 5)
+                   throw "Unexpected component bid: " + bid
+                 return {desirability: 5, allowComponentAuction: true, bid: 4};`,
+            reportResult:
+                `if (browserSignals.bid !== 5)
+                   throw "Unexpected component bid: " + browserSignals.bid;
+                 if (browserSignals.modifiedBid !== 4)
+                   throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
+                 sendReportTo("${componentSellerReportURL}");` });
+
+  auctionConfig.decisionLogicURL =
+      createDecisionScriptURL(
+          uuid,
+          { scoreAd:
+                `if (bid !== 4)
+                   throw "Unexpected top-level bid: " + bid`,
+            reportResult:
+                `if (browserSignals.bid !== 4)
+                   throw "Unexpected top-level bid: " + browserSignals.bid;
+                 if (browserSignals.modifiedBid !== undefined)
+                   throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
+                 sendReportTo("${topLevelSellerReportURL}");` });
+
+  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
+  await waitForObservedRequests(
+      uuid,
+      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
+}, 'Component auction modified bid.');
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  let bidderReportURL = createBidderReportURL(uuid);
+  let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/1);
+  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/2);
+
+  await joinInterestGroup(
+      test, uuid,
+      { biddingLogicURL: createBiddingScriptURL(
+        { allowComponentAuction: true,
+          bid: 5,
+          reportWin:
+            `if (browserSignals.bid !== 5)
+               throw "Unexpected bid: " + browserSignals.bid;
+             sendReportTo("${bidderReportURL}");`})});
+
+  let auctionConfig = createComponentAuctionConfig(uuid);
+
+  auctionConfig.componentAuctions[0].decisionLogicURL =
+      createDecisionScriptURL(
+          uuid,
+          { scoreAd:
+                `if (bid !== 5)
+                   throw "Unexpected component bid: " + bid
+                 return {desirability: 5, allowComponentAuction: true, bid: 5};`,
+            reportResult:
+                `if (browserSignals.bid !== 5)
+                   throw "Unexpected component bid: " + browserSignals.bid;
+                 if (browserSignals.modifiedBid !== 5)
+                   throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
+                 sendReportTo("${componentSellerReportURL}");` });
+
+  auctionConfig.decisionLogicURL =
+      createDecisionScriptURL(
+          uuid,
+          { scoreAd:
+                `if (bid !== 5)
+                   throw "Unexpected top-level bid: " + bid`,
+            reportResult:
+                `if (browserSignals.bid !== 5)
+                   throw "Unexpected top-level bid: " + browserSignals.bid;
+                 if (browserSignals.modifiedBid !== undefined)
+                   throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
+                 sendReportTo("${topLevelSellerReportURL}");` });
+
+  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
+  await waitForObservedRequests(
+      uuid,
+      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
+}, 'Component auction modified bid to same value.');
+
+subsetTest(promise_test, async test => {
+  const uuid = generateUuid(test);
+
+  let bidderReportURL = createBidderReportURL(uuid);
+  let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/1);
+  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/2);
+
+  await joinInterestGroup(
+      test, uuid,
+      { biddingLogicURL: createBiddingScriptURL(
+        { allowComponentAuction: true,
+          bid: 5,
+          reportWin:
+            `if (browserSignals.bid !== 5)
+               throw "Unexpected bid: " + browserSignals.bid;
+             sendReportTo("${bidderReportURL}");`})});
+
+  let auctionConfig = createComponentAuctionConfig(uuid);
+
+  auctionConfig.componentAuctions[0].decisionLogicURL =
+      createDecisionScriptURL(
+          uuid,
+          { scoreAd:
+                `if (bid !== 5)
+                   throw "Unexpected component bid: " + bid`,
+            reportResult:
+                `if (browserSignals.bid !== 5)
+                   throw "Unexpected component bid: " + browserSignals.bid;
+                 if (browserSignals.modifiedBid !== undefined)
+                   throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
+                 sendReportTo("${componentSellerReportURL}");` });
+
+  auctionConfig.decisionLogicURL =
+      createDecisionScriptURL(
+          uuid,
+          { scoreAd:
+                `if (bid !== 5)
+                   throw "Unexpected top-level bid: " + bid
+                 return {desirability: 5, allowComponentAuction: true, bid: 4};`,
+            reportResult:
+                `if (browserSignals.bid !== 5)
+                   throw "Unexpected top-level bid: " + browserSignals.bid;
+                 if (browserSignals.modifiedBid !== undefined)
+                   throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
+                 sendReportTo("${topLevelSellerReportURL}");` });
+
+  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
+  await waitForObservedRequests(
+      uuid,
+      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
+}, 'Top-level auction cannot modify bid.');
diff --git a/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-childiframe-crossorigin.html b/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-childiframe-crossorigin.html
index b8607f9..03f3dbf 100644
--- a/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-childiframe-crossorigin.html
+++ b/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-childiframe-crossorigin.html
@@ -5,11 +5,16 @@
 
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 <script src='resources/utils.js'></script>
 
 <h1>Long Task in Nested Cross-Origin Child Iframe</h1>
 <div id="log"></div>
 <script>
+  const child_url = new URL("resources/subframe-with-longtask.html",
+                            new URL(location.pathname,
+                                    get_host_info().HTTPS_REMOTE_ORIGIN)).href;
+
   async_test(function (t) {
     assert_implements(window.PerformanceLongTaskTiming, 'Longtasks are not supported.');
     const observer = new PerformanceObserver(
@@ -35,8 +40,7 @@
             assert_equals(attribution.containerType, 'iframe');
             assert_equals(attribution.containerId, 'child-iframe-id');
             assert_equals(attribution.containerName, 'child-iframe-name');
-            assert_equals(attribution.containerSrc,
-                'resources/subframe-with-longtask.html');
+            assert_equals(attribution.containerSrc, child_url);
             observer.disconnect();
             t.done();
         })
@@ -46,10 +50,8 @@
         const iframe = document.createElement('iframe');
         iframe.id = 'child-iframe-id';
         iframe.name = 'child-iframe-name';
-        // Simulate cross-origin by using sandbox.
-        iframe.sandbox = "allow-scripts";
         document.body.appendChild(iframe);
-        iframe.src = 'resources/subframe-with-longtask.html';
+        iframe.src = child_url;
     };
 }, 'Performance longtask entries in cross-origin child iframe are observable in parent.');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-sibling-iframe-crossorigin.html b/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-sibling-iframe-crossorigin.html
index d66fe0c6..25f1918f 100644
--- a/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-sibling-iframe-crossorigin.html
+++ b/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-sibling-iframe-crossorigin.html
@@ -5,8 +5,13 @@
 
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
 
 <script>
+  const sibling_url = new URL("resources/subframe-with-longtask.html",
+                              new URL(location.pathname,
+                                      get_host_info().HTTPS_REMOTE_ORIGIN)).href;
+
   async_test(t => {
     assert_implements(window.PerformanceLongTaskTiming, 'Longtasks are not supported.');
     window.addEventListener('message', t.step_func(e => {
@@ -30,10 +35,8 @@
       const longtaskFrame = document.createElement('iframe');
       longtaskFrame.id = 'longtask-iframe-id';
       longtaskFrame.name = 'longtask-iframe-name';
-      // Simulate cross-origin by using sandbox.
-      longtaskFrame.sandbox = "allow-scripts";
       document.body.appendChild(longtaskFrame);
-      longtaskFrame.src = 'resources/subframe-with-longtask.html'
+      longtaskFrame.src = sibling_url;
     };
 }, 'Performance longtask entries from cross-origin iframe are observable in its sibling.');
 </script>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-ignoredNodesModal-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-ignoredNodesModal-expected.txt
index 1385ce6..f9e7277 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-ignoredNodesModal-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-ignoredNodesModal-expected.txt
@@ -57,20 +57,13 @@
     parentId : <string>
     properties : [
         [0] : {
-            name : focusable
-            value : {
-                type : booleanOrUndefined
-                value : true
-            }
-        }
-        [1] : {
             name : focused
             value : {
                 type : booleanOrUndefined
                 value : true
             }
         }
-        [2] : {
+        [1] : {
             name : modal
             value : {
                 type : boolean
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-modal-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-modal-expected.txt
index 508d187..7d124779 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-modal-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-modal-expected.txt
@@ -266,20 +266,13 @@
     parentId : <string>
     properties : [
         [0] : {
-            name : focusable
-            value : {
-                type : booleanOrUndefined
-                value : true
-            }
-        }
-        [1] : {
             name : focused
             value : {
                 type : booleanOrUndefined
                 value : true
             }
         }
-        [2] : {
+        [1] : {
             name : modal
             value : {
                 type : boolean
diff --git a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-allow-pointer-lock.html b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-allow-pointer-lock.html
index d8fefe7c..b1fa843 100644
--- a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-allow-pointer-lock.html
+++ b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-allow-pointer-lock.html
@@ -17,7 +17,7 @@
         }
       });
       function onIframeLoaded() {
-        clickOnElement(iframe);
+          iframe.contentWindow.postMessage([ "clickBody" ], "*");
       }
       var iframe = document.createElement('iframe');
       iframe.sandbox = 'allow-pointer-lock allow-scripts';
diff --git a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-allow-pointer-lock.html b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-allow-pointer-lock.html
index 733828e..ad983c99 100644
--- a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-allow-pointer-lock.html
+++ b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-allow-pointer-lock.html
@@ -18,7 +18,7 @@
       });
       window.addEventListener('message', (event) => {
         if (event.data == 'inner frame load') {
-          clickOnElement(iframe);
+          iframe.contentWindow.postMessage([ "clickBody" ], "*");
         }
       });
       var iframe = document.createElement('iframe');
diff --git a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-disallow-then-allow-pointer-lock.html b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-disallow-then-allow-pointer-lock.html
index 805e28b..588260e 100644
--- a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-disallow-then-allow-pointer-lock.html
+++ b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-disallow-then-allow-pointer-lock.html
@@ -18,7 +18,7 @@
       });
       window.addEventListener('message', (event) => {
         if (event.data == 'inner frame load') {
-          clickOnElement(iframe);
+          iframe.contentWindow.postMessage([ "clickBody" ], "*");
         }
       });
       var iframe = document.createElement('iframe');
diff --git a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed.html b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed.html
index b543bb7d..b5d8f53 100644
--- a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed.html
+++ b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed.html
@@ -17,7 +17,7 @@
         }
       });
       function onIframeLoaded() {
-        clickOnElement(iframe);
+        iframe.contentWindow.postMessage([ "clickBody" ], "*");
       }
       var iframe = document.createElement('iframe');
       iframe.sandbox = 'allow-scripts';
diff --git a/third_party/blink/web_tests/http/tests/resources/pointer-lock/iframe-allows-inner-iframe.html b/third_party/blink/web_tests/http/tests/resources/pointer-lock/iframe-allows-inner-iframe.html
index dc0e61e..c3a39a56 100644
--- a/third_party/blink/web_tests/http/tests/resources/pointer-lock/iframe-allows-inner-iframe.html
+++ b/third_party/blink/web_tests/http/tests/resources/pointer-lock/iframe-allows-inner-iframe.html
@@ -8,11 +8,15 @@
         parent.postMessage('inner frame load', '*');
     }
     window.addEventListener('message', (event) => {
-        parent.postMessage(event.data, '*');
+        if (event.data[0] == "clickBody") {
+            document.getElementById("nested-child").contentWindow.postMessage(event.data, "*");
+        } else {
+            parent.postMessage(event.data, '*');
+        }
     });
 </script>
 <body>
-    <iframe src="inner-iframe.html" sandbox="allow-pointer-lock allow-scripts" onload="onInnerFrameLoad()"></iframe>
+    <iframe id="nested-child" src="inner-iframe.html" sandbox="allow-pointer-lock allow-scripts" onload="onInnerFrameLoad()"></iframe>
     iframe-allows-inner-iframe.html
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/http/tests/resources/pointer-lock/iframe-common.js b/third_party/blink/web_tests/http/tests/resources/pointer-lock/iframe-common.js
index 5562484..d110b59 100644
--- a/third_party/blink/web_tests/http/tests/resources/pointer-lock/iframe-common.js
+++ b/third_party/blink/web_tests/http/tests/resources/pointer-lock/iframe-common.js
@@ -12,6 +12,9 @@
         iframe = document.getElementsByTagName("iframe")[0];
         iframe.contentWindow.postMessage(messageEvent.data.slice(1), "*");
         break;
+    case "clickBody":
+        // The child frame consumes this, do not pass back to parent.
+        break;
     default:
         // Pass all other messages up to parent.
         parent.postMessage(messageEvent.data, "*");
@@ -19,6 +22,8 @@
 }
 
 document.onpointerlockchange = function () {
+    console.log('wjm: document.pointerLockElement = ' + document.pointerLockElement +
+                ', document.url = ' + document.URL);
     parent.postMessage(thisFileName() + " onpointerlockchange, document.pointerLockElement = " + document.pointerLockElement, "*");
 }
 
diff --git a/third_party/blink/web_tests/http/tests/resources/pointer-lock/inner-iframe.html b/third_party/blink/web_tests/http/tests/resources/pointer-lock/inner-iframe.html
index 7a9b05f4..25594be 100644
--- a/third_party/blink/web_tests/http/tests/resources/pointer-lock/inner-iframe.html
+++ b/third_party/blink/web_tests/http/tests/resources/pointer-lock/inner-iframe.html
@@ -1,8 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
+<script src="pointer-lock-test-harness.js"></script>
 <script src="iframe-common.js"></script>
 <script>
+    window.addEventListener('message', (e)=> {
+        if (e.data[0] === "clickBody") {
+            clickOnElement(document.body);
+        }
+    });
+
     document.addEventListener('click', () => {
         document.body.requestPointerLock().catch(error => {
             // Do nothing here. The errors returned in the promise are
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/IndexedDB/back-forward-cache-open-connection.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/IndexedDB/back-forward-cache-open-connection.window-expected.txt
new file mode 100644
index 0000000..a1183b85
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/IndexedDB/back-forward-cache-open-connection.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Testing BFCache support for page with open IndexedDB connection, and eviction behavior when receiving versionchange event.
+  BFCache not supported.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/IndexedDB/back-forward-cache-open-transaction.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/IndexedDB/back-forward-cache-open-transaction.window-expected.txt
new file mode 100644
index 0000000..199d8d94
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/IndexedDB/back-forward-cache-open-transaction.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] BFCache support test for page with open IndexedDB transaction
+  BFCache not supported.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/Accelerometer-iframe-access.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/Accelerometer-iframe-access.https-expected.txt
new file mode 100644
index 0000000..941fbe2c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/Accelerometer-iframe-access.https-expected.txt
@@ -0,0 +1,17 @@
+This is a testharness.js-based test.
+[FAIL] Accelerometer: unfocused sensors in cross-origin frames are not updated
+  promise_test: Unhandled rejection with value: "NotAllowedError: Permissions to access sensor are not granted"
+[PASS] Accelerometer: sensors in same-origin frames are updated if one of the frames is focused
+[PASS] Accelerometer: losing a document's frame with an active sensor does not crash
+[PASS] Accelerometer: calling start() in a non-fully active document does not crash
+[FAIL] LinearAccelerationSensor: unfocused sensors in cross-origin frames are not updated
+  promise_test: Unhandled rejection with value: "NotAllowedError: Permissions to access sensor are not granted"
+[PASS] LinearAccelerationSensor: sensors in same-origin frames are updated if one of the frames is focused
+[PASS] LinearAccelerationSensor: losing a document's frame with an active sensor does not crash
+[PASS] LinearAccelerationSensor: calling start() in a non-fully active document does not crash
+[FAIL] GravitySensor: unfocused sensors in cross-origin frames are not updated
+  promise_test: Unhandled rejection with value: "NotAllowedError: Permissions to access sensor are not granted"
+[PASS] GravitySensor: sensors in same-origin frames are updated if one of the frames is focused
+[PASS] GravitySensor: losing a document's frame with an active sensor does not crash
+[PASS] GravitySensor: calling start() in a non-fully active document does not crash
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/Accelerometer.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/Accelerometer.https-expected.txt
new file mode 100644
index 0000000..8aea4497
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/Accelerometer.https-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+[PASS] Accelerometer: Test that onerror is sent when permissions are not granted.
+[PASS] Accelerometer: Test that onerror is send when start() call has failed.
+[PASS] Accelerometer: Test that frequency is capped to allowed maximum.
+[PASS] Accelerometer: Test that frequency is capped to the maximum supported frequency.
+[PASS] Accelerometer: Test that frequency is limited to the minimum supported frequency.
+[PASS] Accelerometer: Test that sensor cannot be constructed within iframe disallowed to use feature policy.
+[PASS] Accelerometer: Test that sensor can be constructed within an iframe allowed to use feature policy.
+[PASS] Accelerometer: Test that 'onreading' is called and sensor reading is valid.
+[PASS] Accelerometer: sensor reading is correct.
+[PASS] Accelerometer: Test that readings are all mapped to expectedReadings correctly.
+[PASS] Accelerometer: sensor timestamp is updated when time passes.
+[PASS] Accelerometer: Test that sensor can be successfully created and its states are correct.
+[PASS] Accelerometer: no exception is thrown when calling start() on already started sensor.
+[PASS] Accelerometer: no exception is thrown when calling stop() on already stopped sensor.
+[PASS] Accelerometer: Test that fresh reading is fetched on start().
+[FAIL] Accelerometer: Readings are not delivered when the page has no visibility
+  assert_true: expected true got false
+[PASS] Accelerometer: frequency hint works.
+[PASS] Accelerometer: Readings delivered by shared platform sensor are immediately accessible to all sensors.
+[PASS] Accelerometer: throw 'TypeError' if frequency is invalid.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/GravitySensor.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/GravitySensor.https-expected.txt
new file mode 100644
index 0000000..0c83eeb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/GravitySensor.https-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+[PASS] GravitySensor: Test that onerror is sent when permissions are not granted.
+[PASS] GravitySensor: Test that onerror is send when start() call has failed.
+[PASS] GravitySensor: Test that frequency is capped to allowed maximum.
+[PASS] GravitySensor: Test that frequency is capped to the maximum supported frequency.
+[PASS] GravitySensor: Test that frequency is limited to the minimum supported frequency.
+[PASS] GravitySensor: Test that sensor cannot be constructed within iframe disallowed to use feature policy.
+[PASS] GravitySensor: Test that sensor can be constructed within an iframe allowed to use feature policy.
+[PASS] GravitySensor: Test that 'onreading' is called and sensor reading is valid.
+[PASS] GravitySensor: sensor reading is correct.
+[PASS] GravitySensor: Test that readings are all mapped to expectedReadings correctly.
+[PASS] GravitySensor: sensor timestamp is updated when time passes.
+[PASS] GravitySensor: Test that sensor can be successfully created and its states are correct.
+[PASS] GravitySensor: no exception is thrown when calling start() on already started sensor.
+[PASS] GravitySensor: no exception is thrown when calling stop() on already stopped sensor.
+[PASS] GravitySensor: Test that fresh reading is fetched on start().
+[FAIL] GravitySensor: Readings are not delivered when the page has no visibility
+  assert_true: expected true got false
+[PASS] GravitySensor: frequency hint works.
+[PASS] GravitySensor: Readings delivered by shared platform sensor are immediately accessible to all sensors.
+[PASS] GravitySensor: throw 'TypeError' if frequency is invalid.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/LinearAccelerationSensor.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/LinearAccelerationSensor.https-expected.txt
new file mode 100644
index 0000000..9aaebe8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/accelerometer/LinearAccelerationSensor.https-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+[PASS] LinearAccelerationSensor: Test that onerror is sent when permissions are not granted.
+[PASS] LinearAccelerationSensor: Test that onerror is send when start() call has failed.
+[PASS] LinearAccelerationSensor: Test that frequency is capped to allowed maximum.
+[PASS] LinearAccelerationSensor: Test that frequency is capped to the maximum supported frequency.
+[PASS] LinearAccelerationSensor: Test that frequency is limited to the minimum supported frequency.
+[PASS] LinearAccelerationSensor: Test that sensor cannot be constructed within iframe disallowed to use feature policy.
+[PASS] LinearAccelerationSensor: Test that sensor can be constructed within an iframe allowed to use feature policy.
+[PASS] LinearAccelerationSensor: Test that 'onreading' is called and sensor reading is valid.
+[PASS] LinearAccelerationSensor: sensor reading is correct.
+[PASS] LinearAccelerationSensor: Test that readings are all mapped to expectedReadings correctly.
+[PASS] LinearAccelerationSensor: sensor timestamp is updated when time passes.
+[PASS] LinearAccelerationSensor: Test that sensor can be successfully created and its states are correct.
+[PASS] LinearAccelerationSensor: no exception is thrown when calling start() on already started sensor.
+[PASS] LinearAccelerationSensor: no exception is thrown when calling stop() on already stopped sensor.
+[PASS] LinearAccelerationSensor: Test that fresh reading is fetched on start().
+[FAIL] LinearAccelerationSensor: Readings are not delivered when the page has no visibility
+  assert_true: expected true got false
+[PASS] LinearAccelerationSensor: frequency hint works.
+[PASS] LinearAccelerationSensor: Readings delivered by shared platform sensor are immediately accessible to all sensors.
+[PASS] LinearAccelerationSensor: throw 'TypeError' if frequency is invalid.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/attribution-reporting/request-format.sub.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/attribution-reporting/request-format.sub.https-expected.txt
new file mode 100644
index 0000000..930cf11
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/attribution-reporting/request-format.sub.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = javascript error: Unexpected identifier 'eventSourceEligible'\nJavaScript stack:\nSyntaxError: Unexpected identifier 'eventSourceEligible'\n    at new Function (<anonymous>)\n    at executeAsyncScript (<anonymous>:447:26)\n    at <anonymous>:462:29\n    at callFunction (<anonymous>:341:22)\n    at <anonymous>:355:23\n    at <anonymous>:356:3\n  (Session info: chrome-headless-shell=121.0.6106.0)\nTraceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 596, in do_testharness\n    result = protocol.base.execute_script(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 56, in execute_script\n    return method(script)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 735, in execute_async_script\n    return self.send_session_command("POST", "execute/async", body)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 567, in send_command\n    raise err\nwebdriver.error.JavascriptErrorException: javascript error (500): javascript error: Unexpected identifier 'eventSourceEligible'\nJavaScript stack:\nSyntaxError: Unexpected identifier 'eventSourceEligible'\n    at new Function (<anonymous>)\n    at executeAsyncScript (<anonymous>:447:26)\n    at <anonymous>:462:29\n    at callFunction (<anonymous>:341:22)\n    at <anonymous>:355:23\n    at <anonymous>:356:3\n  (Session info: chrome-headless-shell=121.0.6106.0)\n\nRemote-end stacktrace:\n\n#0 0x55c8fb8e5482 <unknown>\n#1 0x55c8fb8d6e03 <unknown>\n#2 0x55c8fb59b7c9 <unknown>\n#3 0x55c8fb5a1a08 <unknown>\n#4 0x55c8fb5a14e6 <unknown>\n#5 0x55c8fb6101c8 <unknown>\n#6 0x55c8fb5f7da2 <unknown>\n#7 0x55c8fb5d1c2f <unknown>\n#8 0x55c8fb60f430 <unknown>\n#9 0x55c8fb5f7a03 <unknown>\n#10 0x55c8fb5d0501 <unknown>\n#11 0x55c8fb5cfd14 <unknown>\n#12 0x55c8fb5d117c <unknown>\n#13 0x55c8fb891a2a <unknown>\n#14 0x55c8fb8aa74c <unknown>\n#15 0x55c8fb8aa16b <unknown>\n#16 0x55c8fb8aabf5 <unknown>\n#17 0x55c8fb89b16f <unknown>\n#18 0x55c8fb8ab0e9 <unknown>\n#19 0x55c8fb883bea <unknown>\n#20 0x55c8fb8c69a8 <unknown>\n#21 0x55c8fb8c6b3a <unknown>\n#22 0x55c8fb8d60d6 <unknown>\n#23 0x7fac42694ac3 <unknown>\n#24 0x7fac42726a40 <unknown>\n\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/attribution-reporting/request-format.sub.https_method=a_expected-eligible=navigation-source-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/attribution-reporting/request-format.sub.https_method=a_expected-eligible=navigation-source-expected.txt
new file mode 100644
index 0000000..1a61401
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/attribution-reporting/request-format.sub.https_method=a_expected-eligible=navigation-source-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] attributionsrc request has the proper format.
+  promise_test: Unhandled rejection with value: object "Error: Tried to run in a non-testharness window without a call to set_test_context"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/attribution-reporting/request-format.sub.https_method=open_expected-eligible=navigation-source-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/attribution-reporting/request-format.sub.https_method=open_expected-eligible=navigation-source-expected.txt
new file mode 100644
index 0000000..1a61401
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/attribution-reporting/request-format.sub.https_method=open_expected-eligible=navigation-source-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] attributionsrc request has the proper format.
+  promise_test: Unhandled rejection with value: object "Error: Tried to run in a non-testharness window without a call to set_test_context"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/battery-status/page-visibility.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/battery-status/page-visibility.https-expected.txt
new file mode 100644
index 0000000..e535ce1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/battery-status/page-visibility.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] battery status events only fire on visible pages
+  assert_equals: expected 0.6 but got 0.55
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/answers.sub.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/answers.sub.https-expected.txt
new file mode 100644
index 0000000..e8acdf0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/answers.sub.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Accept-CH header test
+  assert_true: rtt-received expected true got false
+[PASS] Cross-Origin Accept-CH header test
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/cache-revalidation.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/cache-revalidation.https-expected.txt
new file mode 100644
index 0000000..1f7ec983
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/cache-revalidation.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Same headers sent for revalidation request
+  assert_equals: expected "vhgcfkuxxhkguwurvfgj" but got "ryryshskkhlokhyjwczw"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/feature-policy-navigation/feature-policy.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/feature-policy-navigation/feature-policy.https-expected.txt
new file mode 100644
index 0000000..cdc87a3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/feature-policy-navigation/feature-policy.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PASS] Client hints loaded on cross-origin iframe request with feature policy.
+[FAIL] Client hints loaded on same-origin iframe request with feature policy.
+  promise_test: Unhandled rejection with value: "FAIL rtt True None"
+[PASS] Client hints loaded on cross-origin iframe request with feature policy after attempting to set independently.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/feature-policy-navigation/no-feature-policy.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/feature-policy-navigation/no-feature-policy.https-expected.txt
new file mode 100644
index 0000000..a16e5225
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/feature-policy-navigation/no-feature-policy.https-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[PASS] Client hints not loaded on cross-origin iframe request with no feature policy.
+[FAIL] Client hints loaded on same-origin iframe request with no feature policy.
+  promise_test: Unhandled rejection with value: "FAIL rtt True None"
+[PASS] Client hints loaded on cross-origin iframe request with allow list.
+[FAIL] Client hints loaded on same-origin iframe request with allow list.
+  promise_test: Unhandled rejection with value: "FAIL rtt True None"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/feature-policy.sub.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/feature-policy.sub.https-expected.txt
new file mode 100644
index 0000000..e8acdf0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/feature-policy.sub.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Accept-CH header test
+  assert_true: rtt-received expected true got false
+[PASS] Cross-Origin Accept-CH header test
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/no-feature-policy.sub.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/no-feature-policy.sub.https-expected.txt
new file mode 100644
index 0000000..e8acdf0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/accept-ch/no-feature-policy.sub.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Accept-CH header test
+  assert_true: rtt-received expected true got false
+[PASS] Cross-Origin Accept-CH header test
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/sandbox/iframe-csp-same-origin.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/sandbox/iframe-csp-same-origin.https-expected.txt
new file mode 100644
index 0000000..f9a53d0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/sandbox/iframe-csp-same-origin.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] CSP sandboxed iframe with same-origin flag does send client hint headers
+  assert_equals: message from opened frame expected "PASS" but got "FAIL rtt True None"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/sandbox/iframe-same-origin.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/sandbox/iframe-same-origin.https-expected.txt
new file mode 100644
index 0000000..6110946
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/sandbox/iframe-same-origin.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Same origin sandboxed iframe with allow-same-origin flag does send client hint headers
+  assert_equals: message from opened frame expected "PASS" but got "FAIL rtt True None"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/viewport-size/viewport-size-window-different-dimensions.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/viewport-size/viewport-size-window-different-dimensions.https-expected.txt
new file mode 100644
index 0000000..0cb11db
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/client-hints/viewport-size/viewport-size-window-different-dimensions.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] viewport-size-window-different-dimensions
+  assert_equals: expected "614" but got "600"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-custom-formats-write-read-web-prefix.tentative.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-custom-formats-write-read-web-prefix.tentative.https-expected.txt
new file mode 100644
index 0000000..0a1b100
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-custom-formats-write-read-web-prefix.tentative.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] navigator.clipboard.write() for custom format and Blob type with web prefix
+  assert_equals: expected "input data 1" but got ""
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-custom-formats-write-read-without-web-prefix.tentative.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-custom-formats-write-read-without-web-prefix.tentative.https-expected.txt
new file mode 100644
index 0000000..4b41392
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-custom-formats-write-read-without-web-prefix.tentative.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] navigator.clipboard.write() for custom format with web prefix, but Blob type without web prefix
+  assert_equals: expected "input data 1" but got ""
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-custom-formats-write-read.tentative.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-custom-formats-write-read.tentative.https-expected.txt
new file mode 100644
index 0000000..4a86b32
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-custom-formats-write-read.tentative.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verify write and read clipboard given 2 platform-neutral custom format inputs
+  assert_equals: expected "input data 1" but got ""
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-unsanitized-html-formats-write-read.tentative.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-unsanitized-html-formats-write-read.tentative.https-expected.txt
new file mode 100644
index 0000000..a16f798
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-unsanitized-html-formats-write-read.tentative.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verify write and read unsanitized content to the clipboard given text/html format as input
+  assert_equals: expected "<style>p {color:blue}</style><p>Hello World</p>" but got ""
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-unsanitized-plaintext-formats-write-read.tentative.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-unsanitized-plaintext-formats-write-read.tentative.https-expected.txt
new file mode 100644
index 0000000..1eea2cf1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/clipboard-apis/async-unsanitized-plaintext-formats-write-read.tentative.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verify write and read unsanitized content to the clipboard given standard and custom formats as input
+  assert_equals: expected "Test text." but got ""
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/report-to-directive-allowed-in-meta.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/report-to-directive-allowed-in-meta.https.sub-expected.txt
new file mode 100644
index 0000000..aa0615a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/report-to-directive-allowed-in-meta.https.sub-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Test that image does not load
+[PASS] Event is fired
+[PASS] Report is observable to ReportingObserver
+[FAIL] Violation report status OK.
+  Cannot read properties of undefined (reading 'body')
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/reporting-api-report-only-sends-reports-on-violation.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/reporting-api-report-only-sends-reports-on-violation.https.sub-expected.txt
new file mode 100644
index 0000000..5353d7fc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/reporting-api-report-only-sends-reports-on-violation.https.sub-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PASS] Test that image does not load
+[PASS] Event is fired
+[FAIL] Violation report status OK.
+  Cannot read properties of undefined (reading 'body')
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub-expected.txt
new file mode 100644
index 0000000..aa0615a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Test that image does not load
+[PASS] Event is fired
+[PASS] Report is observable to ReportingObserver
+[FAIL] Violation report status OK.
+  Cannot read properties of undefined (reading 'body')
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/reporting-api-works-on-frame-src.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/reporting-api-works-on-frame-src.https.sub-expected.txt
new file mode 100644
index 0000000..674016d8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/content-security-policy/reporting-api/reporting-api-works-on-frame-src.https.sub-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[PASS] Event is fired
+[FAIL] Violation report status OK.
+  Cannot read properties of undefined (reading 'body')
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-anchor-position/anchor-getComputedStyle-002-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-anchor-position/anchor-getComputedStyle-002-expected.txt
new file mode 100644
index 0000000..be6978a50
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-anchor-position/anchor-getComputedStyle-002-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[PASS] getComputedStyle() with fragmented containing block in multicolumn layout
+[FAIL] getComputedStyle() with fragmented containing block in inline layout
+  assert_equals: expected "20px" but got "0px"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-break/hit-test-transformed-inline-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-break/hit-test-transformed-inline-expected.txt
new file mode 100644
index 0000000..6e09d00
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-break/hit-test-transformed-inline-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+[FAIL] First x
+  assert_equals: expected "span" but got "firstchild"
+[FAIL] First child
+  assert_equals: expected "firstchild" but got "mc"
+[FAIL] Second child
+  assert_equals: expected "secondchild" but got "span"
+[FAIL] Last x
+  assert_equals: expected "span" but got "mc"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-contain/container-queries/font-relative-units-dynamic-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-contain/container-queries/font-relative-units-dynamic-expected.txt
new file mode 100644
index 0000000..425f29ed
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-contain/container-queries/font-relative-units-dynamic-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+[PASS] em units respond to changes
+[PASS] rem units respond to changes
+[PASS] ex units respond to changes
+[PASS] rex units respond to changes
+[PASS] ch units respond to changes
+[FAIL] cap units respond to changes
+  assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
+[PASS] rch units respond to changes
+[PASS] lh units respond to changes
+[PASS] rlh units respond to changes
+[PASS] ic units respond to changes
+[PASS] ric units respond to changes
+[FAIL] rcap units respond to changes
+  assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-contain/container-queries/font-relative-units-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-contain/container-queries/font-relative-units-expected.txt
new file mode 100644
index 0000000..13a9c2f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-contain/container-queries/font-relative-units-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+[PASS] em relative inline-size
+[PASS] rem relative inline-size
+[PASS] ex relative inline-size
+[FAIL] rex relative inline-size
+  assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
+[PASS] ch relative inline-size
+[PASS] rch relative inline-size
+[PASS] ic relative inline-size
+[PASS] ric relative inline-size
+[PASS] lh relative inline-size
+[PASS] rlh relative inline-size
+[PASS] cap relative inline-size
+[FAIL] rcap relative inline-size
+  assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-fonts/cjk-kerning-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-fonts/cjk-kerning-expected.txt
new file mode 100644
index 0000000..b412ccf4d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-fonts/cjk-kerning-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+[PASS] expected match: .kernON .latin vs .paltOFFkernON .latin
+[PASS] expected match: .kernON .latin vs .paltONkernON .latin
+[PASS] expected match: .kernOFF .latin vs .paltONkernOFF .latin
+[PASS] expected match: .kernON .cjk vs .paltONkernON .cjk
+[PASS] expected match: .default .cjk vs .kernOFF .cjk
+[PASS] expected mismatch: .kernOFF .latin vs .kernON .latin
+[FAIL] expected mismatch: .kernOFF .cjk vs .kernON .cjk
+  assert_not_equals: got disallowed value 288
+[FAIL] expected mismatch: .paltOFFkernON .cjk vs .paltONkernON .cjk
+  assert_not_equals: got disallowed value 288
+[PASS] .default .latin matches one of [.kernON .latin, .kernOFF .latin]
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-fonts/fallback-url-to-local-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-fonts/fallback-url-to-local-expected.txt
new file mode 100644
index 0000000..e132eadf
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-fonts/fallback-url-to-local-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] We should use the local font to render the page when the primary remote font is loading
+  assert_equals: expected 250 but got 150
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-fonts/font-face-range-order-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-fonts/font-face-range-order-expected.txt
new file mode 100644
index 0000000..d348ea16
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-fonts/font-face-range-order-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] CSS Fonts Module Level 3: Order of values in @font-face range descriptors
+  promise_test: Unhandled rejection with value: object "NetworkError: A network error occurred."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-multicol/getclientrects-000-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-multicol/getclientrects-000-expected.txt
new file mode 100644
index 0000000..65c512c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-multicol/getclientrects-000-expected.txt
@@ -0,0 +1,14 @@
+This is a testharness.js-based test.
+[FAIL] horizontal-tb ltr
+  assert_equals: expected 70 but got 69
+[FAIL] vertical-lr ltr
+  assert_equals: expected 120 but got 119
+[FAIL] vertical-rl ltr
+  assert_equals: expected 100 but got 99
+[FAIL] horizontal-tb rtl
+  assert_equals: expected 310 but got 332.21875
+[FAIL] vertical-lr rtl
+  assert_equals: expected 120 but got 119
+[FAIL] vertical-rl rtl
+  assert_equals: expected 100 but got 99
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-circle-004-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-circle-004-expected.txt
new file mode 100644
index 0000000..1f4206d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-circle-004-expected.txt
@@ -0,0 +1,1135 @@
+This is a testharness.js-based test.
+Found 780 tests; 428 PASS, 352 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] test unit (inline): cm - circle(at 50cm)
+[PASS] test unit (inline): cm - circle(at 50% 50cm)
+[PASS] test unit (inline): cm - circle(at 50cm 50%)
+[PASS] test unit (inline): cm - circle(at 50cm 50cm)
+[PASS] test unit (inline): cm - circle(at left 50cm)
+[PASS] test unit (inline): cm - circle(at 50cm top)
+[PASS] test unit (inline): cm - circle(at right 80cm)
+[PASS] test unit (inline): cm - circle(at 70cm bottom)
+[PASS] test unit (inline): cm - circle(at center 60cm)
+[PASS] test unit (inline): cm - circle(at 60cm center)
+[PASS] test unit (inline): cm - circle(at left 50% top 50cm)
+[FAIL] test unit (inline): cm - circle(at left 50% bottom 70cm)
+  assert_equals: expected "circle(at 50% calc(100% - 2645.67px))" but got "circle(at left 50% bottom 70cm)"
+[PASS] test unit (inline): cm - circle(at left 50cm top 50%)
+[PASS] test unit (inline): cm - circle(at left 50cm top 50cm)
+[FAIL] test unit (inline): cm - circle(at left 50cm bottom 70%)
+  assert_equals: expected "circle(at 50cm calc(30%))" but got "circle(at 50cm 30%)"
+[PASS] test unit (inline): cm - circle(at top 50% left 50cm)
+[FAIL] test unit (inline): cm - circle(at top 50% right 80cm)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) 50%)" but got "circle(at right 80cm top 50%)"
+[PASS] test unit (inline): cm - circle(at top 50cm left 50%)
+[PASS] test unit (inline): cm - circle(at top 50cm left 50cm)
+[FAIL] test unit (inline): cm - circle(at top 50cm right 80%)
+  assert_equals: expected "circle(at calc(20%) 50cm)" but got "circle(at 20% 50cm)"
+[FAIL] test unit (inline): cm - circle(at bottom 70% left 50cm)
+  assert_equals: expected "circle(at 50cm calc(30%))" but got "circle(at 50cm 30%)"
+[FAIL] test unit (inline): cm - circle(at bottom 70% right 80cm)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) calc(30%))" but got "circle(at right 80cm top 30%)"
+[FAIL] test unit (inline): cm - circle(at bottom 70cm left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 2645.67px))" but got "circle(at left 50% bottom 70cm)"
+[FAIL] test unit (inline): cm - circle(at bottom 70cm right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 2645.67px))" but got "circle(at left 50% bottom 70cm)"
+[FAIL] test unit (inline): cm - circle(at bottom 70cm right 80cm)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) calc(100% - 2645.67px))" but got "circle(at right 80cm bottom 70cm)"
+[FAIL] test unit (inline): cm - circle(at right 80% top 50cm)
+  assert_equals: expected "circle(at calc(20%) 50cm)" but got "circle(at 20% 50cm)"
+[FAIL] test unit (inline): cm - circle(at right 80% bottom 70cm)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 2645.67px))" but got "circle(at left 20% bottom 70cm)"
+[FAIL] test unit (inline): cm - circle(at right 80cm top 50%)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) 50%)" but got "circle(at right 80cm top 50%)"
+[FAIL] test unit (inline): cm - circle(at right 80cm bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) calc(30%))" but got "circle(at right 80cm top 30%)"
+[FAIL] test unit (inline): cm - circle(at right 80cm bottom 70cm)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) calc(100% - 2645.67px))" but got "circle(at right 80cm bottom 70cm)"
+[PASS] test unit (inline): mm - circle(at 50mm)
+[PASS] test unit (inline): mm - circle(at 50% 50mm)
+[PASS] test unit (inline): mm - circle(at 50mm 50%)
+[PASS] test unit (inline): mm - circle(at 50mm 50mm)
+[PASS] test unit (inline): mm - circle(at left 50mm)
+[PASS] test unit (inline): mm - circle(at 50mm top)
+[PASS] test unit (inline): mm - circle(at right 80mm)
+[PASS] test unit (inline): mm - circle(at 70mm bottom)
+[PASS] test unit (inline): mm - circle(at center 60mm)
+[PASS] test unit (inline): mm - circle(at 60mm center)
+[PASS] test unit (inline): mm - circle(at left 50% top 50mm)
+[FAIL] test unit (inline): mm - circle(at left 50% bottom 70mm)
+  assert_equals: expected "circle(at 50% calc(100% - 264.567px))" but got "circle(at left 50% bottom 70mm)"
+[PASS] test unit (inline): mm - circle(at left 50mm top 50%)
+[PASS] test unit (inline): mm - circle(at left 50mm top 50mm)
+[FAIL] test unit (inline): mm - circle(at left 50mm bottom 70%)
+  assert_equals: expected "circle(at 50mm calc(30%))" but got "circle(at 50mm 30%)"
+[PASS] test unit (inline): mm - circle(at top 50% left 50mm)
+[FAIL] test unit (inline): mm - circle(at top 50% right 80mm)
+  assert_equals: expected "circle(at calc(100% - 302.362px) 50%)" but got "circle(at right 80mm top 50%)"
+[PASS] test unit (inline): mm - circle(at top 50mm left 50%)
+[PASS] test unit (inline): mm - circle(at top 50mm left 50mm)
+[FAIL] test unit (inline): mm - circle(at top 50mm right 80%)
+  assert_equals: expected "circle(at calc(20%) 50mm)" but got "circle(at 20% 50mm)"
+[FAIL] test unit (inline): mm - circle(at bottom 70% left 50mm)
+  assert_equals: expected "circle(at 50mm calc(30%))" but got "circle(at 50mm 30%)"
+[FAIL] test unit (inline): mm - circle(at bottom 70% right 80mm)
+  assert_equals: expected "circle(at calc(100% - 302.362px) calc(30%))" but got "circle(at right 80mm top 30%)"
+[FAIL] test unit (inline): mm - circle(at bottom 70mm left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 264.567px))" but got "circle(at left 50% bottom 70mm)"
+[FAIL] test unit (inline): mm - circle(at bottom 70mm right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 264.567px))" but got "circle(at left 50% bottom 70mm)"
+[FAIL] test unit (inline): mm - circle(at bottom 70mm right 80mm)
+  assert_equals: expected "circle(at calc(100% - 302.362px) calc(100% - 264.567px))" but got "circle(at right 80mm bottom 70mm)"
+[FAIL] test unit (inline): mm - circle(at right 80% top 50mm)
+  assert_equals: expected "circle(at calc(20%) 50mm)" but got "circle(at 20% 50mm)"
+[FAIL] test unit (inline): mm - circle(at right 80% bottom 70mm)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 264.567px))" but got "circle(at left 20% bottom 70mm)"
+[FAIL] test unit (inline): mm - circle(at right 80mm top 50%)
+  assert_equals: expected "circle(at calc(100% - 302.362px) 50%)" but got "circle(at right 80mm top 50%)"
+[FAIL] test unit (inline): mm - circle(at right 80mm bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 302.362px) calc(30%))" but got "circle(at right 80mm top 30%)"
+[FAIL] test unit (inline): mm - circle(at right 80mm bottom 70mm)
+  assert_equals: expected "circle(at calc(100% - 302.362px) calc(100% - 264.567px))" but got "circle(at right 80mm bottom 70mm)"
+[PASS] test unit (inline): in - circle(at 50in)
+[PASS] test unit (inline): in - circle(at 50% 50in)
+[PASS] test unit (inline): in - circle(at 50in 50%)
+[PASS] test unit (inline): in - circle(at 50in 50in)
+[PASS] test unit (inline): in - circle(at left 50in)
+[PASS] test unit (inline): in - circle(at 50in top)
+[PASS] test unit (inline): in - circle(at right 80in)
+[PASS] test unit (inline): in - circle(at 70in bottom)
+[PASS] test unit (inline): in - circle(at center 60in)
+[PASS] test unit (inline): in - circle(at 60in center)
+[PASS] test unit (inline): in - circle(at left 50% top 50in)
+[FAIL] test unit (inline): in - circle(at left 50% bottom 70in)
+  assert_equals: expected "circle(at 50% calc(100% - 6720px))" but got "circle(at left 50% bottom 70in)"
+[PASS] test unit (inline): in - circle(at left 50in top 50%)
+[PASS] test unit (inline): in - circle(at left 50in top 50in)
+[FAIL] test unit (inline): in - circle(at left 50in bottom 70%)
+  assert_equals: expected "circle(at 50in calc(30%))" but got "circle(at 50in 30%)"
+[PASS] test unit (inline): in - circle(at top 50% left 50in)
+[FAIL] test unit (inline): in - circle(at top 50% right 80in)
+  assert_equals: expected "circle(at calc(100% - 7680px) 50%)" but got "circle(at right 80in top 50%)"
+[PASS] test unit (inline): in - circle(at top 50in left 50%)
+[PASS] test unit (inline): in - circle(at top 50in left 50in)
+[FAIL] test unit (inline): in - circle(at top 50in right 80%)
+  assert_equals: expected "circle(at calc(20%) 50in)" but got "circle(at 20% 50in)"
+[FAIL] test unit (inline): in - circle(at bottom 70% left 50in)
+  assert_equals: expected "circle(at 50in calc(30%))" but got "circle(at 50in 30%)"
+[FAIL] test unit (inline): in - circle(at bottom 70% right 80in)
+  assert_equals: expected "circle(at calc(100% - 7680px) calc(30%))" but got "circle(at right 80in top 30%)"
+[FAIL] test unit (inline): in - circle(at bottom 70in left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 6720px))" but got "circle(at left 50% bottom 70in)"
+[FAIL] test unit (inline): in - circle(at bottom 70in right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 6720px))" but got "circle(at left 50% bottom 70in)"
+[FAIL] test unit (inline): in - circle(at bottom 70in right 80in)
+  assert_equals: expected "circle(at calc(100% - 7680px) calc(100% - 6720px))" but got "circle(at right 80in bottom 70in)"
+[FAIL] test unit (inline): in - circle(at right 80% top 50in)
+  assert_equals: expected "circle(at calc(20%) 50in)" but got "circle(at 20% 50in)"
+[FAIL] test unit (inline): in - circle(at right 80% bottom 70in)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 6720px))" but got "circle(at left 20% bottom 70in)"
+[FAIL] test unit (inline): in - circle(at right 80in top 50%)
+  assert_equals: expected "circle(at calc(100% - 7680px) 50%)" but got "circle(at right 80in top 50%)"
+[FAIL] test unit (inline): in - circle(at right 80in bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 7680px) calc(30%))" but got "circle(at right 80in top 30%)"
+[FAIL] test unit (inline): in - circle(at right 80in bottom 70in)
+  assert_equals: expected "circle(at calc(100% - 7680px) calc(100% - 6720px))" but got "circle(at right 80in bottom 70in)"
+[PASS] test unit (inline): pt - circle(at 50pt)
+[PASS] test unit (inline): pt - circle(at 50% 50pt)
+[PASS] test unit (inline): pt - circle(at 50pt 50%)
+[PASS] test unit (inline): pt - circle(at 50pt 50pt)
+[PASS] test unit (inline): pt - circle(at left 50pt)
+[PASS] test unit (inline): pt - circle(at 50pt top)
+[PASS] test unit (inline): pt - circle(at right 80pt)
+[PASS] test unit (inline): pt - circle(at 70pt bottom)
+[PASS] test unit (inline): pt - circle(at center 60pt)
+[PASS] test unit (inline): pt - circle(at 60pt center)
+[PASS] test unit (inline): pt - circle(at left 50% top 50pt)
+[FAIL] test unit (inline): pt - circle(at left 50% bottom 70pt)
+  assert_equals: expected "circle(at 50% calc(100% - 93.3333px))" but got "circle(at left 50% bottom 70pt)"
+[PASS] test unit (inline): pt - circle(at left 50pt top 50%)
+[PASS] test unit (inline): pt - circle(at left 50pt top 50pt)
+[FAIL] test unit (inline): pt - circle(at left 50pt bottom 70%)
+  assert_equals: expected "circle(at 50pt calc(30%))" but got "circle(at 50pt 30%)"
+[PASS] test unit (inline): pt - circle(at top 50% left 50pt)
+[FAIL] test unit (inline): pt - circle(at top 50% right 80pt)
+  assert_equals: expected "circle(at calc(100% - 106.667px) 50%)" but got "circle(at right 80pt top 50%)"
+[PASS] test unit (inline): pt - circle(at top 50pt left 50%)
+[PASS] test unit (inline): pt - circle(at top 50pt left 50pt)
+[FAIL] test unit (inline): pt - circle(at top 50pt right 80%)
+  assert_equals: expected "circle(at calc(20%) 50pt)" but got "circle(at 20% 50pt)"
+[FAIL] test unit (inline): pt - circle(at bottom 70% left 50pt)
+  assert_equals: expected "circle(at 50pt calc(30%))" but got "circle(at 50pt 30%)"
+[FAIL] test unit (inline): pt - circle(at bottom 70% right 80pt)
+  assert_equals: expected "circle(at calc(100% - 106.667px) calc(30%))" but got "circle(at right 80pt top 30%)"
+[FAIL] test unit (inline): pt - circle(at bottom 70pt left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 93.3333px))" but got "circle(at left 50% bottom 70pt)"
+[FAIL] test unit (inline): pt - circle(at bottom 70pt right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 93.3333px))" but got "circle(at left 50% bottom 70pt)"
+[FAIL] test unit (inline): pt - circle(at bottom 70pt right 80pt)
+  assert_equals: expected "circle(at calc(100% - 106.667px) calc(100% - 93.3333px))" but got "circle(at right 80pt bottom 70pt)"
+[FAIL] test unit (inline): pt - circle(at right 80% top 50pt)
+  assert_equals: expected "circle(at calc(20%) 50pt)" but got "circle(at 20% 50pt)"
+[FAIL] test unit (inline): pt - circle(at right 80% bottom 70pt)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 93.3333px))" but got "circle(at left 20% bottom 70pt)"
+[FAIL] test unit (inline): pt - circle(at right 80pt top 50%)
+  assert_equals: expected "circle(at calc(100% - 106.667px) 50%)" but got "circle(at right 80pt top 50%)"
+[FAIL] test unit (inline): pt - circle(at right 80pt bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 106.667px) calc(30%))" but got "circle(at right 80pt top 30%)"
+[FAIL] test unit (inline): pt - circle(at right 80pt bottom 70pt)
+  assert_equals: expected "circle(at calc(100% - 106.667px) calc(100% - 93.3333px))" but got "circle(at right 80pt bottom 70pt)"
+[PASS] test unit (inline): pc - circle(at 50pc)
+[PASS] test unit (inline): pc - circle(at 50% 50pc)
+[PASS] test unit (inline): pc - circle(at 50pc 50%)
+[PASS] test unit (inline): pc - circle(at 50pc 50pc)
+[PASS] test unit (inline): pc - circle(at left 50pc)
+[PASS] test unit (inline): pc - circle(at 50pc top)
+[PASS] test unit (inline): pc - circle(at right 80pc)
+[PASS] test unit (inline): pc - circle(at 70pc bottom)
+[PASS] test unit (inline): pc - circle(at center 60pc)
+[PASS] test unit (inline): pc - circle(at 60pc center)
+[PASS] test unit (inline): pc - circle(at left 50% top 50pc)
+[FAIL] test unit (inline): pc - circle(at left 50% bottom 70pc)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 70pc)"
+[PASS] test unit (inline): pc - circle(at left 50pc top 50%)
+[PASS] test unit (inline): pc - circle(at left 50pc top 50pc)
+[FAIL] test unit (inline): pc - circle(at left 50pc bottom 70%)
+  assert_equals: expected "circle(at 50pc calc(30%))" but got "circle(at 50pc 30%)"
+[PASS] test unit (inline): pc - circle(at top 50% left 50pc)
+[FAIL] test unit (inline): pc - circle(at top 50% right 80pc)
+  assert_equals: expected "circle(at calc(100% - 1280px) 50%)" but got "circle(at right 80pc top 50%)"
+[PASS] test unit (inline): pc - circle(at top 50pc left 50%)
+[PASS] test unit (inline): pc - circle(at top 50pc left 50pc)
+[FAIL] test unit (inline): pc - circle(at top 50pc right 80%)
+  assert_equals: expected "circle(at calc(20%) 50pc)" but got "circle(at 20% 50pc)"
+[FAIL] test unit (inline): pc - circle(at bottom 70% left 50pc)
+  assert_equals: expected "circle(at 50pc calc(30%))" but got "circle(at 50pc 30%)"
+[FAIL] test unit (inline): pc - circle(at bottom 70% right 80pc)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(30%))" but got "circle(at right 80pc top 30%)"
+[FAIL] test unit (inline): pc - circle(at bottom 70pc left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 70pc)"
+[FAIL] test unit (inline): pc - circle(at bottom 70pc right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 1120px))" but got "circle(at left 50% bottom 70pc)"
+[FAIL] test unit (inline): pc - circle(at bottom 70pc right 80pc)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(100% - 1120px))" but got "circle(at right 80pc bottom 70pc)"
+[FAIL] test unit (inline): pc - circle(at right 80% top 50pc)
+  assert_equals: expected "circle(at calc(20%) 50pc)" but got "circle(at 20% 50pc)"
+[FAIL] test unit (inline): pc - circle(at right 80% bottom 70pc)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 1120px))" but got "circle(at left 20% bottom 70pc)"
+[FAIL] test unit (inline): pc - circle(at right 80pc top 50%)
+  assert_equals: expected "circle(at calc(100% - 1280px) 50%)" but got "circle(at right 80pc top 50%)"
+[FAIL] test unit (inline): pc - circle(at right 80pc bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(30%))" but got "circle(at right 80pc top 30%)"
+[FAIL] test unit (inline): pc - circle(at right 80pc bottom 70pc)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(100% - 1120px))" but got "circle(at right 80pc bottom 70pc)"
+[PASS] test unit (inline): em - circle(at 50em)
+[PASS] test unit (inline): em - circle(at 50% 50em)
+[PASS] test unit (inline): em - circle(at 50em 50%)
+[PASS] test unit (inline): em - circle(at 50em 50em)
+[PASS] test unit (inline): em - circle(at left 50em)
+[PASS] test unit (inline): em - circle(at 50em top)
+[PASS] test unit (inline): em - circle(at right 80em)
+[PASS] test unit (inline): em - circle(at 70em bottom)
+[PASS] test unit (inline): em - circle(at center 60em)
+[PASS] test unit (inline): em - circle(at 60em center)
+[PASS] test unit (inline): em - circle(at left 50% top 50em)
+[FAIL] test unit (inline): em - circle(at left 50% bottom 70em)
+  assert_equals: expected "circle(at 50% calc(100% - 70em))" but got "circle(at left 50% bottom 70em)"
+[PASS] test unit (inline): em - circle(at left 50em top 50%)
+[PASS] test unit (inline): em - circle(at left 50em top 50em)
+[FAIL] test unit (inline): em - circle(at left 50em bottom 70%)
+  assert_equals: expected "circle(at 50em calc(30%))" but got "circle(at 50em 30%)"
+[PASS] test unit (inline): em - circle(at top 50% left 50em)
+[FAIL] test unit (inline): em - circle(at top 50% right 80em)
+  assert_equals: expected "circle(at calc(100% - 80em) 50%)" but got "circle(at right 80em top 50%)"
+[PASS] test unit (inline): em - circle(at top 50em left 50%)
+[PASS] test unit (inline): em - circle(at top 50em left 50em)
+[FAIL] test unit (inline): em - circle(at top 50em right 80%)
+  assert_equals: expected "circle(at calc(20%) 50em)" but got "circle(at 20% 50em)"
+[FAIL] test unit (inline): em - circle(at bottom 70% left 50em)
+  assert_equals: expected "circle(at 50em calc(30%))" but got "circle(at 50em 30%)"
+[FAIL] test unit (inline): em - circle(at bottom 70% right 80em)
+  assert_equals: expected "circle(at calc(100% - 80em) calc(30%))" but got "circle(at right 80em top 30%)"
+[FAIL] test unit (inline): em - circle(at bottom 70em left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 70em))" but got "circle(at left 50% bottom 70em)"
+[FAIL] test unit (inline): em - circle(at bottom 70em right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 70em))" but got "circle(at left 50% bottom 70em)"
+[FAIL] test unit (inline): em - circle(at bottom 70em right 80em)
+  assert_equals: expected "circle(at calc(100% - 80em) calc(100% - 70em))" but got "circle(at right 80em bottom 70em)"
+[FAIL] test unit (inline): em - circle(at right 80% top 50em)
+  assert_equals: expected "circle(at calc(20%) 50em)" but got "circle(at 20% 50em)"
+[FAIL] test unit (inline): em - circle(at right 80% bottom 70em)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 70em))" but got "circle(at left 20% bottom 70em)"
+[FAIL] test unit (inline): em - circle(at right 80em top 50%)
+  assert_equals: expected "circle(at calc(100% - 80em) 50%)" but got "circle(at right 80em top 50%)"
+[FAIL] test unit (inline): em - circle(at right 80em bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 80em) calc(30%))" but got "circle(at right 80em top 30%)"
+[FAIL] test unit (inline): em - circle(at right 80em bottom 70em)
+  assert_equals: expected "circle(at calc(100% - 80em) calc(100% - 70em))" but got "circle(at right 80em bottom 70em)"
+[PASS] test unit (inline): ex - circle(at 50ex)
+[PASS] test unit (inline): ex - circle(at 50% 50ex)
+[PASS] test unit (inline): ex - circle(at 50ex 50%)
+[PASS] test unit (inline): ex - circle(at 50ex 50ex)
+[PASS] test unit (inline): ex - circle(at left 50ex)
+[PASS] test unit (inline): ex - circle(at 50ex top)
+[PASS] test unit (inline): ex - circle(at right 80ex)
+[PASS] test unit (inline): ex - circle(at 70ex bottom)
+[PASS] test unit (inline): ex - circle(at center 60ex)
+[PASS] test unit (inline): ex - circle(at 60ex center)
+[PASS] test unit (inline): ex - circle(at left 50% top 50ex)
+[FAIL] test unit (inline): ex - circle(at left 50% bottom 70ex)
+  assert_equals: expected "circle(at 50% calc(100% - 70ex))" but got "circle(at left 50% bottom 70ex)"
+[PASS] test unit (inline): ex - circle(at left 50ex top 50%)
+[PASS] test unit (inline): ex - circle(at left 50ex top 50ex)
+[FAIL] test unit (inline): ex - circle(at left 50ex bottom 70%)
+  assert_equals: expected "circle(at 50ex calc(30%))" but got "circle(at 50ex 30%)"
+[PASS] test unit (inline): ex - circle(at top 50% left 50ex)
+[FAIL] test unit (inline): ex - circle(at top 50% right 80ex)
+  assert_equals: expected "circle(at calc(100% - 80ex) 50%)" but got "circle(at right 80ex top 50%)"
+[PASS] test unit (inline): ex - circle(at top 50ex left 50%)
+[PASS] test unit (inline): ex - circle(at top 50ex left 50ex)
+[FAIL] test unit (inline): ex - circle(at top 50ex right 80%)
+  assert_equals: expected "circle(at calc(20%) 50ex)" but got "circle(at 20% 50ex)"
+[FAIL] test unit (inline): ex - circle(at bottom 70% left 50ex)
+  assert_equals: expected "circle(at 50ex calc(30%))" but got "circle(at 50ex 30%)"
+[FAIL] test unit (inline): ex - circle(at bottom 70% right 80ex)
+  assert_equals: expected "circle(at calc(100% - 80ex) calc(30%))" but got "circle(at right 80ex top 30%)"
+[FAIL] test unit (inline): ex - circle(at bottom 70ex left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 70ex))" but got "circle(at left 50% bottom 70ex)"
+[FAIL] test unit (inline): ex - circle(at bottom 70ex right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 70ex))" but got "circle(at left 50% bottom 70ex)"
+[FAIL] test unit (inline): ex - circle(at bottom 70ex right 80ex)
+  assert_equals: expected "circle(at calc(100% - 80ex) calc(100% - 70ex))" but got "circle(at right 80ex bottom 70ex)"
+[FAIL] test unit (inline): ex - circle(at right 80% top 50ex)
+  assert_equals: expected "circle(at calc(20%) 50ex)" but got "circle(at 20% 50ex)"
+[FAIL] test unit (inline): ex - circle(at right 80% bottom 70ex)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 70ex))" but got "circle(at left 20% bottom 70ex)"
+[FAIL] test unit (inline): ex - circle(at right 80ex top 50%)
+  assert_equals: expected "circle(at calc(100% - 80ex) 50%)" but got "circle(at right 80ex top 50%)"
+[FAIL] test unit (inline): ex - circle(at right 80ex bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 80ex) calc(30%))" but got "circle(at right 80ex top 30%)"
+[FAIL] test unit (inline): ex - circle(at right 80ex bottom 70ex)
+  assert_equals: expected "circle(at calc(100% - 80ex) calc(100% - 70ex))" but got "circle(at right 80ex bottom 70ex)"
+[PASS] test unit (inline): ch - circle(at 50ch)
+[PASS] test unit (inline): ch - circle(at 50% 50ch)
+[PASS] test unit (inline): ch - circle(at 50ch 50%)
+[PASS] test unit (inline): ch - circle(at 50ch 50ch)
+[PASS] test unit (inline): ch - circle(at left 50ch)
+[PASS] test unit (inline): ch - circle(at 50ch top)
+[PASS] test unit (inline): ch - circle(at right 80ch)
+[PASS] test unit (inline): ch - circle(at 70ch bottom)
+[PASS] test unit (inline): ch - circle(at center 60ch)
+[PASS] test unit (inline): ch - circle(at 60ch center)
+[PASS] test unit (inline): ch - circle(at left 50% top 50ch)
+[FAIL] test unit (inline): ch - circle(at left 50% bottom 70ch)
+  assert_equals: expected "circle(at 50% calc(100% - 70ch))" but got "circle(at left 50% bottom 70ch)"
+[PASS] test unit (inline): ch - circle(at left 50ch top 50%)
+[PASS] test unit (inline): ch - circle(at left 50ch top 50ch)
+[FAIL] test unit (inline): ch - circle(at left 50ch bottom 70%)
+  assert_equals: expected "circle(at 50ch calc(30%))" but got "circle(at 50ch 30%)"
+[PASS] test unit (inline): ch - circle(at top 50% left 50ch)
+[FAIL] test unit (inline): ch - circle(at top 50% right 80ch)
+  assert_equals: expected "circle(at calc(100% - 80ch) 50%)" but got "circle(at right 80ch top 50%)"
+[PASS] test unit (inline): ch - circle(at top 50ch left 50%)
+[PASS] test unit (inline): ch - circle(at top 50ch left 50ch)
+[FAIL] test unit (inline): ch - circle(at top 50ch right 80%)
+  assert_equals: expected "circle(at calc(20%) 50ch)" but got "circle(at 20% 50ch)"
+[FAIL] test unit (inline): ch - circle(at bottom 70% left 50ch)
+  assert_equals: expected "circle(at 50ch calc(30%))" but got "circle(at 50ch 30%)"
+[FAIL] test unit (inline): ch - circle(at bottom 70% right 80ch)
+  assert_equals: expected "circle(at calc(100% - 80ch) calc(30%))" but got "circle(at right 80ch top 30%)"
+[FAIL] test unit (inline): ch - circle(at bottom 70ch left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 70ch))" but got "circle(at left 50% bottom 70ch)"
+[FAIL] test unit (inline): ch - circle(at bottom 70ch right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 70ch))" but got "circle(at left 50% bottom 70ch)"
+[FAIL] test unit (inline): ch - circle(at bottom 70ch right 80ch)
+  assert_equals: expected "circle(at calc(100% - 80ch) calc(100% - 70ch))" but got "circle(at right 80ch bottom 70ch)"
+[FAIL] test unit (inline): ch - circle(at right 80% top 50ch)
+  assert_equals: expected "circle(at calc(20%) 50ch)" but got "circle(at 20% 50ch)"
+[FAIL] test unit (inline): ch - circle(at right 80% bottom 70ch)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 70ch))" but got "circle(at left 20% bottom 70ch)"
+[FAIL] test unit (inline): ch - circle(at right 80ch top 50%)
+  assert_equals: expected "circle(at calc(100% - 80ch) 50%)" but got "circle(at right 80ch top 50%)"
+[FAIL] test unit (inline): ch - circle(at right 80ch bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 80ch) calc(30%))" but got "circle(at right 80ch top 30%)"
+[FAIL] test unit (inline): ch - circle(at right 80ch bottom 70ch)
+  assert_equals: expected "circle(at calc(100% - 80ch) calc(100% - 70ch))" but got "circle(at right 80ch bottom 70ch)"
+[PASS] test unit (inline): rem - circle(at 50rem)
+[PASS] test unit (inline): rem - circle(at 50% 50rem)
+[PASS] test unit (inline): rem - circle(at 50rem 50%)
+[PASS] test unit (inline): rem - circle(at 50rem 50rem)
+[PASS] test unit (inline): rem - circle(at left 50rem)
+[PASS] test unit (inline): rem - circle(at 50rem top)
+[PASS] test unit (inline): rem - circle(at right 80rem)
+[PASS] test unit (inline): rem - circle(at 70rem bottom)
+[PASS] test unit (inline): rem - circle(at center 60rem)
+[PASS] test unit (inline): rem - circle(at 60rem center)
+[PASS] test unit (inline): rem - circle(at left 50% top 50rem)
+[FAIL] test unit (inline): rem - circle(at left 50% bottom 70rem)
+  assert_equals: expected "circle(at 50% calc(100% - 70rem))" but got "circle(at left 50% bottom 70rem)"
+[PASS] test unit (inline): rem - circle(at left 50rem top 50%)
+[PASS] test unit (inline): rem - circle(at left 50rem top 50rem)
+[FAIL] test unit (inline): rem - circle(at left 50rem bottom 70%)
+  assert_equals: expected "circle(at 50rem calc(30%))" but got "circle(at 50rem 30%)"
+[PASS] test unit (inline): rem - circle(at top 50% left 50rem)
+[FAIL] test unit (inline): rem - circle(at top 50% right 80rem)
+  assert_equals: expected "circle(at calc(100% - 80rem) 50%)" but got "circle(at right 80rem top 50%)"
+[PASS] test unit (inline): rem - circle(at top 50rem left 50%)
+[PASS] test unit (inline): rem - circle(at top 50rem left 50rem)
+[FAIL] test unit (inline): rem - circle(at top 50rem right 80%)
+  assert_equals: expected "circle(at calc(20%) 50rem)" but got "circle(at 20% 50rem)"
+[FAIL] test unit (inline): rem - circle(at bottom 70% left 50rem)
+  assert_equals: expected "circle(at 50rem calc(30%))" but got "circle(at 50rem 30%)"
+[FAIL] test unit (inline): rem - circle(at bottom 70% right 80rem)
+  assert_equals: expected "circle(at calc(100% - 80rem) calc(30%))" but got "circle(at right 80rem top 30%)"
+[FAIL] test unit (inline): rem - circle(at bottom 70rem left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 70rem))" but got "circle(at left 50% bottom 70rem)"
+[FAIL] test unit (inline): rem - circle(at bottom 70rem right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 70rem))" but got "circle(at left 50% bottom 70rem)"
+[FAIL] test unit (inline): rem - circle(at bottom 70rem right 80rem)
+  assert_equals: expected "circle(at calc(100% - 80rem) calc(100% - 70rem))" but got "circle(at right 80rem bottom 70rem)"
+[FAIL] test unit (inline): rem - circle(at right 80% top 50rem)
+  assert_equals: expected "circle(at calc(20%) 50rem)" but got "circle(at 20% 50rem)"
+[FAIL] test unit (inline): rem - circle(at right 80% bottom 70rem)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 70rem))" but got "circle(at left 20% bottom 70rem)"
+[FAIL] test unit (inline): rem - circle(at right 80rem top 50%)
+  assert_equals: expected "circle(at calc(100% - 80rem) 50%)" but got "circle(at right 80rem top 50%)"
+[FAIL] test unit (inline): rem - circle(at right 80rem bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 80rem) calc(30%))" but got "circle(at right 80rem top 30%)"
+[FAIL] test unit (inline): rem - circle(at right 80rem bottom 70rem)
+  assert_equals: expected "circle(at calc(100% - 80rem) calc(100% - 70rem))" but got "circle(at right 80rem bottom 70rem)"
+[PASS] test unit (inline): vw - circle(at 50vw)
+[PASS] test unit (inline): vw - circle(at 50% 50vw)
+[PASS] test unit (inline): vw - circle(at 50vw 50%)
+[PASS] test unit (inline): vw - circle(at 50vw 50vw)
+[PASS] test unit (inline): vw - circle(at left 50vw)
+[PASS] test unit (inline): vw - circle(at 50vw top)
+[PASS] test unit (inline): vw - circle(at right 80vw)
+[PASS] test unit (inline): vw - circle(at 70vw bottom)
+[PASS] test unit (inline): vw - circle(at center 60vw)
+[PASS] test unit (inline): vw - circle(at 60vw center)
+[PASS] test unit (inline): vw - circle(at left 50% top 50vw)
+[FAIL] test unit (inline): vw - circle(at left 50% bottom 70vw)
+  assert_equals: expected "circle(at 50% calc(100% - 70vw))" but got "circle(at left 50% bottom 70vw)"
+[PASS] test unit (inline): vw - circle(at left 50vw top 50%)
+[PASS] test unit (inline): vw - circle(at left 50vw top 50vw)
+[FAIL] test unit (inline): vw - circle(at left 50vw bottom 70%)
+  assert_equals: expected "circle(at 50vw calc(30%))" but got "circle(at 50vw 30%)"
+[PASS] test unit (inline): vw - circle(at top 50% left 50vw)
+[FAIL] test unit (inline): vw - circle(at top 50% right 80vw)
+  assert_equals: expected "circle(at calc(100% - 80vw) 50%)" but got "circle(at right 80vw top 50%)"
+[PASS] test unit (inline): vw - circle(at top 50vw left 50%)
+[PASS] test unit (inline): vw - circle(at top 50vw left 50vw)
+[FAIL] test unit (inline): vw - circle(at top 50vw right 80%)
+  assert_equals: expected "circle(at calc(20%) 50vw)" but got "circle(at 20% 50vw)"
+[FAIL] test unit (inline): vw - circle(at bottom 70% left 50vw)
+  assert_equals: expected "circle(at 50vw calc(30%))" but got "circle(at 50vw 30%)"
+[FAIL] test unit (inline): vw - circle(at bottom 70% right 80vw)
+  assert_equals: expected "circle(at calc(100% - 80vw) calc(30%))" but got "circle(at right 80vw top 30%)"
+[FAIL] test unit (inline): vw - circle(at bottom 70vw left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 70vw))" but got "circle(at left 50% bottom 70vw)"
+[FAIL] test unit (inline): vw - circle(at bottom 70vw right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 70vw))" but got "circle(at left 50% bottom 70vw)"
+[FAIL] test unit (inline): vw - circle(at bottom 70vw right 80vw)
+  assert_equals: expected "circle(at calc(100% - 80vw) calc(100% - 70vw))" but got "circle(at right 80vw bottom 70vw)"
+[FAIL] test unit (inline): vw - circle(at right 80% top 50vw)
+  assert_equals: expected "circle(at calc(20%) 50vw)" but got "circle(at 20% 50vw)"
+[FAIL] test unit (inline): vw - circle(at right 80% bottom 70vw)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 70vw))" but got "circle(at left 20% bottom 70vw)"
+[FAIL] test unit (inline): vw - circle(at right 80vw top 50%)
+  assert_equals: expected "circle(at calc(100% - 80vw) 50%)" but got "circle(at right 80vw top 50%)"
+[FAIL] test unit (inline): vw - circle(at right 80vw bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 80vw) calc(30%))" but got "circle(at right 80vw top 30%)"
+[FAIL] test unit (inline): vw - circle(at right 80vw bottom 70vw)
+  assert_equals: expected "circle(at calc(100% - 80vw) calc(100% - 70vw))" but got "circle(at right 80vw bottom 70vw)"
+[PASS] test unit (inline): vh - circle(at 50vh)
+[PASS] test unit (inline): vh - circle(at 50% 50vh)
+[PASS] test unit (inline): vh - circle(at 50vh 50%)
+[PASS] test unit (inline): vh - circle(at 50vh 50vh)
+[PASS] test unit (inline): vh - circle(at left 50vh)
+[PASS] test unit (inline): vh - circle(at 50vh top)
+[PASS] test unit (inline): vh - circle(at right 80vh)
+[PASS] test unit (inline): vh - circle(at 70vh bottom)
+[PASS] test unit (inline): vh - circle(at center 60vh)
+[PASS] test unit (inline): vh - circle(at 60vh center)
+[PASS] test unit (inline): vh - circle(at left 50% top 50vh)
+[FAIL] test unit (inline): vh - circle(at left 50% bottom 70vh)
+  assert_equals: expected "circle(at 50% calc(100% - 70vh))" but got "circle(at left 50% bottom 70vh)"
+[PASS] test unit (inline): vh - circle(at left 50vh top 50%)
+[PASS] test unit (inline): vh - circle(at left 50vh top 50vh)
+[FAIL] test unit (inline): vh - circle(at left 50vh bottom 70%)
+  assert_equals: expected "circle(at 50vh calc(30%))" but got "circle(at 50vh 30%)"
+[PASS] test unit (inline): vh - circle(at top 50% left 50vh)
+[FAIL] test unit (inline): vh - circle(at top 50% right 80vh)
+  assert_equals: expected "circle(at calc(100% - 80vh) 50%)" but got "circle(at right 80vh top 50%)"
+[PASS] test unit (inline): vh - circle(at top 50vh left 50%)
+[PASS] test unit (inline): vh - circle(at top 50vh left 50vh)
+[FAIL] test unit (inline): vh - circle(at top 50vh right 80%)
+  assert_equals: expected "circle(at calc(20%) 50vh)" but got "circle(at 20% 50vh)"
+[FAIL] test unit (inline): vh - circle(at bottom 70% left 50vh)
+  assert_equals: expected "circle(at 50vh calc(30%))" but got "circle(at 50vh 30%)"
+[FAIL] test unit (inline): vh - circle(at bottom 70% right 80vh)
+  assert_equals: expected "circle(at calc(100% - 80vh) calc(30%))" but got "circle(at right 80vh top 30%)"
+[FAIL] test unit (inline): vh - circle(at bottom 70vh left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 70vh))" but got "circle(at left 50% bottom 70vh)"
+[FAIL] test unit (inline): vh - circle(at bottom 70vh right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 70vh))" but got "circle(at left 50% bottom 70vh)"
+[FAIL] test unit (inline): vh - circle(at bottom 70vh right 80vh)
+  assert_equals: expected "circle(at calc(100% - 80vh) calc(100% - 70vh))" but got "circle(at right 80vh bottom 70vh)"
+[FAIL] test unit (inline): vh - circle(at right 80% top 50vh)
+  assert_equals: expected "circle(at calc(20%) 50vh)" but got "circle(at 20% 50vh)"
+[FAIL] test unit (inline): vh - circle(at right 80% bottom 70vh)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 70vh))" but got "circle(at left 20% bottom 70vh)"
+[FAIL] test unit (inline): vh - circle(at right 80vh top 50%)
+  assert_equals: expected "circle(at calc(100% - 80vh) 50%)" but got "circle(at right 80vh top 50%)"
+[FAIL] test unit (inline): vh - circle(at right 80vh bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 80vh) calc(30%))" but got "circle(at right 80vh top 30%)"
+[FAIL] test unit (inline): vh - circle(at right 80vh bottom 70vh)
+  assert_equals: expected "circle(at calc(100% - 80vh) calc(100% - 70vh))" but got "circle(at right 80vh bottom 70vh)"
+[PASS] test unit (inline): vmin - circle(at 50vmin)
+[PASS] test unit (inline): vmin - circle(at 50% 50vmin)
+[PASS] test unit (inline): vmin - circle(at 50vmin 50%)
+[PASS] test unit (inline): vmin - circle(at 50vmin 50vmin)
+[PASS] test unit (inline): vmin - circle(at left 50vmin)
+[PASS] test unit (inline): vmin - circle(at 50vmin top)
+[PASS] test unit (inline): vmin - circle(at right 80vmin)
+[PASS] test unit (inline): vmin - circle(at 70vmin bottom)
+[PASS] test unit (inline): vmin - circle(at center 60vmin)
+[PASS] test unit (inline): vmin - circle(at 60vmin center)
+[PASS] test unit (inline): vmin - circle(at left 50% top 50vmin)
+[FAIL] test unit (inline): vmin - circle(at left 50% bottom 70vmin)
+  assert_equals: expected "circle(at 50% calc(100% - 70vmin))" but got "circle(at left 50% bottom 70vmin)"
+[PASS] test unit (inline): vmin - circle(at left 50vmin top 50%)
+[PASS] test unit (inline): vmin - circle(at left 50vmin top 50vmin)
+[FAIL] test unit (inline): vmin - circle(at left 50vmin bottom 70%)
+  assert_equals: expected "circle(at 50vmin calc(30%))" but got "circle(at 50vmin 30%)"
+[PASS] test unit (inline): vmin - circle(at top 50% left 50vmin)
+[FAIL] test unit (inline): vmin - circle(at top 50% right 80vmin)
+  assert_equals: expected "circle(at calc(100% - 80vmin) 50%)" but got "circle(at right 80vmin top 50%)"
+[PASS] test unit (inline): vmin - circle(at top 50vmin left 50%)
+[PASS] test unit (inline): vmin - circle(at top 50vmin left 50vmin)
+[FAIL] test unit (inline): vmin - circle(at top 50vmin right 80%)
+  assert_equals: expected "circle(at calc(20%) 50vmin)" but got "circle(at 20% 50vmin)"
+[FAIL] test unit (inline): vmin - circle(at bottom 70% left 50vmin)
+  assert_equals: expected "circle(at 50vmin calc(30%))" but got "circle(at 50vmin 30%)"
+[FAIL] test unit (inline): vmin - circle(at bottom 70% right 80vmin)
+  assert_equals: expected "circle(at calc(100% - 80vmin) calc(30%))" but got "circle(at right 80vmin top 30%)"
+[FAIL] test unit (inline): vmin - circle(at bottom 70vmin left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 70vmin))" but got "circle(at left 50% bottom 70vmin)"
+[FAIL] test unit (inline): vmin - circle(at bottom 70vmin right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 70vmin))" but got "circle(at left 50% bottom 70vmin)"
+[FAIL] test unit (inline): vmin - circle(at bottom 70vmin right 80vmin)
+  assert_equals: expected "circle(at calc(100% - 80vmin) calc(100% - 70vmin))" but got "circle(at right 80vmin bottom 70vmin)"
+[FAIL] test unit (inline): vmin - circle(at right 80% top 50vmin)
+  assert_equals: expected "circle(at calc(20%) 50vmin)" but got "circle(at 20% 50vmin)"
+[FAIL] test unit (inline): vmin - circle(at right 80% bottom 70vmin)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 70vmin))" but got "circle(at left 20% bottom 70vmin)"
+[FAIL] test unit (inline): vmin - circle(at right 80vmin top 50%)
+  assert_equals: expected "circle(at calc(100% - 80vmin) 50%)" but got "circle(at right 80vmin top 50%)"
+[FAIL] test unit (inline): vmin - circle(at right 80vmin bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 80vmin) calc(30%))" but got "circle(at right 80vmin top 30%)"
+[FAIL] test unit (inline): vmin - circle(at right 80vmin bottom 70vmin)
+  assert_equals: expected "circle(at calc(100% - 80vmin) calc(100% - 70vmin))" but got "circle(at right 80vmin bottom 70vmin)"
+[PASS] test unit (inline): vmax - circle(at 50vmax)
+[PASS] test unit (inline): vmax - circle(at 50% 50vmax)
+[PASS] test unit (inline): vmax - circle(at 50vmax 50%)
+[PASS] test unit (inline): vmax - circle(at 50vmax 50vmax)
+[PASS] test unit (inline): vmax - circle(at left 50vmax)
+[PASS] test unit (inline): vmax - circle(at 50vmax top)
+[PASS] test unit (inline): vmax - circle(at right 80vmax)
+[PASS] test unit (inline): vmax - circle(at 70vmax bottom)
+[PASS] test unit (inline): vmax - circle(at center 60vmax)
+[PASS] test unit (inline): vmax - circle(at 60vmax center)
+[PASS] test unit (inline): vmax - circle(at left 50% top 50vmax)
+[FAIL] test unit (inline): vmax - circle(at left 50% bottom 70vmax)
+  assert_equals: expected "circle(at 50% calc(100% - 70vmax))" but got "circle(at left 50% bottom 70vmax)"
+[PASS] test unit (inline): vmax - circle(at left 50vmax top 50%)
+[PASS] test unit (inline): vmax - circle(at left 50vmax top 50vmax)
+[FAIL] test unit (inline): vmax - circle(at left 50vmax bottom 70%)
+  assert_equals: expected "circle(at 50vmax calc(30%))" but got "circle(at 50vmax 30%)"
+[PASS] test unit (inline): vmax - circle(at top 50% left 50vmax)
+[FAIL] test unit (inline): vmax - circle(at top 50% right 80vmax)
+  assert_equals: expected "circle(at calc(100% - 80vmax) 50%)" but got "circle(at right 80vmax top 50%)"
+[PASS] test unit (inline): vmax - circle(at top 50vmax left 50%)
+[PASS] test unit (inline): vmax - circle(at top 50vmax left 50vmax)
+[FAIL] test unit (inline): vmax - circle(at top 50vmax right 80%)
+  assert_equals: expected "circle(at calc(20%) 50vmax)" but got "circle(at 20% 50vmax)"
+[FAIL] test unit (inline): vmax - circle(at bottom 70% left 50vmax)
+  assert_equals: expected "circle(at 50vmax calc(30%))" but got "circle(at 50vmax 30%)"
+[FAIL] test unit (inline): vmax - circle(at bottom 70% right 80vmax)
+  assert_equals: expected "circle(at calc(100% - 80vmax) calc(30%))" but got "circle(at right 80vmax top 30%)"
+[FAIL] test unit (inline): vmax - circle(at bottom 70vmax left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 70vmax))" but got "circle(at left 50% bottom 70vmax)"
+[FAIL] test unit (inline): vmax - circle(at bottom 70vmax right 50%)
+  assert_equals: expected "circle(at calc(50%) calc(100% - 70vmax))" but got "circle(at left 50% bottom 70vmax)"
+[FAIL] test unit (inline): vmax - circle(at bottom 70vmax right 80vmax)
+  assert_equals: expected "circle(at calc(100% - 80vmax) calc(100% - 70vmax))" but got "circle(at right 80vmax bottom 70vmax)"
+[FAIL] test unit (inline): vmax - circle(at right 80% top 50vmax)
+  assert_equals: expected "circle(at calc(20%) 50vmax)" but got "circle(at 20% 50vmax)"
+[FAIL] test unit (inline): vmax - circle(at right 80% bottom 70vmax)
+  assert_equals: expected "circle(at calc(20%) calc(100% - 70vmax))" but got "circle(at left 20% bottom 70vmax)"
+[FAIL] test unit (inline): vmax - circle(at right 80vmax top 50%)
+  assert_equals: expected "circle(at calc(100% - 80vmax) 50%)" but got "circle(at right 80vmax top 50%)"
+[FAIL] test unit (inline): vmax - circle(at right 80vmax bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 80vmax) calc(30%))" but got "circle(at right 80vmax top 30%)"
+[FAIL] test unit (inline): vmax - circle(at right 80vmax bottom 70vmax)
+  assert_equals: expected "circle(at calc(100% - 80vmax) calc(100% - 70vmax))" but got "circle(at right 80vmax bottom 70vmax)"
+[PASS] test unit (computed): cm - circle(at 50cm)
+[PASS] test unit (computed): cm - circle(at 50% 50cm)
+[PASS] test unit (computed): cm - circle(at 50cm 50%)
+[PASS] test unit (computed): cm - circle(at 50cm 50cm)
+[PASS] test unit (computed): cm - circle(at left 50cm)
+[PASS] test unit (computed): cm - circle(at 50cm top)
+[PASS] test unit (computed): cm - circle(at right 80cm)
+[PASS] test unit (computed): cm - circle(at 70cm bottom)
+[PASS] test unit (computed): cm - circle(at center 60cm)
+[PASS] test unit (computed): cm - circle(at 60cm center)
+[PASS] test unit (computed): cm - circle(at left 50% top 50cm)
+[FAIL] test unit (computed): cm - circle(at left 50% bottom 70cm)
+  assert_equals: expected "circle(at 50% calc(100% - 2645.67px))" but got "circle(at left 50% bottom 2645.67px)"
+[PASS] test unit (computed): cm - circle(at left 50cm top 50%)
+[PASS] test unit (computed): cm - circle(at left 50cm top 50cm)
+[PASS] test unit (computed): cm - circle(at left 50cm bottom 70%)
+[PASS] test unit (computed): cm - circle(at top 50% left 50cm)
+[FAIL] test unit (computed): cm - circle(at top 50% right 80cm)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) 50%)" but got "circle(at right 3023.62px top 50%)"
+[PASS] test unit (computed): cm - circle(at top 50cm left 50%)
+[PASS] test unit (computed): cm - circle(at top 50cm left 50cm)
+[PASS] test unit (computed): cm - circle(at top 50cm right 80%)
+[PASS] test unit (computed): cm - circle(at bottom 70% left 50cm)
+[FAIL] test unit (computed): cm - circle(at bottom 70% right 80cm)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) 30%)" but got "circle(at right 3023.62px top 30%)"
+[FAIL] test unit (computed): cm - circle(at bottom 70cm left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 2645.67px))" but got "circle(at left 50% bottom 2645.67px)"
+[FAIL] test unit (computed): cm - circle(at bottom 70cm right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 2645.67px))" but got "circle(at left 50% bottom 2645.67px)"
+[FAIL] test unit (computed): cm - circle(at bottom 70cm right 80cm)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) calc(100% - 2645.67px))" but got "circle(at right 3023.62px bottom 2645.67px)"
+[PASS] test unit (computed): cm - circle(at right 80% top 50cm)
+[FAIL] test unit (computed): cm - circle(at right 80% bottom 70cm)
+  assert_equals: expected "circle(at 20% calc(100% - 2645.67px))" but got "circle(at left 20% bottom 2645.67px)"
+[FAIL] test unit (computed): cm - circle(at right 80cm top 50%)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) 50%)" but got "circle(at right 3023.62px top 50%)"
+[FAIL] test unit (computed): cm - circle(at right 80cm bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) 30%)" but got "circle(at right 3023.62px top 30%)"
+[FAIL] test unit (computed): cm - circle(at right 80cm bottom 70cm)
+  assert_equals: expected "circle(at calc(100% - 3023.62px) calc(100% - 2645.67px))" but got "circle(at right 3023.62px bottom 2645.67px)"
+[PASS] test unit (computed): mm - circle(at 50mm)
+[PASS] test unit (computed): mm - circle(at 50% 50mm)
+[PASS] test unit (computed): mm - circle(at 50mm 50%)
+[PASS] test unit (computed): mm - circle(at 50mm 50mm)
+[PASS] test unit (computed): mm - circle(at left 50mm)
+[PASS] test unit (computed): mm - circle(at 50mm top)
+[PASS] test unit (computed): mm - circle(at right 80mm)
+[PASS] test unit (computed): mm - circle(at 70mm bottom)
+[PASS] test unit (computed): mm - circle(at center 60mm)
+[PASS] test unit (computed): mm - circle(at 60mm center)
+[PASS] test unit (computed): mm - circle(at left 50% top 50mm)
+[FAIL] test unit (computed): mm - circle(at left 50% bottom 70mm)
+  assert_equals: expected "circle(at 50% calc(100% - 264.567px))" but got "circle(at left 50% bottom 264.567px)"
+[PASS] test unit (computed): mm - circle(at left 50mm top 50%)
+[PASS] test unit (computed): mm - circle(at left 50mm top 50mm)
+[PASS] test unit (computed): mm - circle(at left 50mm bottom 70%)
+[PASS] test unit (computed): mm - circle(at top 50% left 50mm)
+[FAIL] test unit (computed): mm - circle(at top 50% right 80mm)
+  assert_equals: expected "circle(at calc(100% - 302.362px) 50%)" but got "circle(at right 302.362px top 50%)"
+[PASS] test unit (computed): mm - circle(at top 50mm left 50%)
+[PASS] test unit (computed): mm - circle(at top 50mm left 50mm)
+[PASS] test unit (computed): mm - circle(at top 50mm right 80%)
+[PASS] test unit (computed): mm - circle(at bottom 70% left 50mm)
+[FAIL] test unit (computed): mm - circle(at bottom 70% right 80mm)
+  assert_equals: expected "circle(at calc(100% - 302.362px) 30%)" but got "circle(at right 302.362px top 30%)"
+[FAIL] test unit (computed): mm - circle(at bottom 70mm left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 264.567px))" but got "circle(at left 50% bottom 264.567px)"
+[FAIL] test unit (computed): mm - circle(at bottom 70mm right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 264.567px))" but got "circle(at left 50% bottom 264.567px)"
+[FAIL] test unit (computed): mm - circle(at bottom 70mm right 80mm)
+  assert_equals: expected "circle(at calc(100% - 302.362px) calc(100% - 264.567px))" but got "circle(at right 302.362px bottom 264.567px)"
+[PASS] test unit (computed): mm - circle(at right 80% top 50mm)
+[FAIL] test unit (computed): mm - circle(at right 80% bottom 70mm)
+  assert_equals: expected "circle(at 20% calc(100% - 264.567px))" but got "circle(at left 20% bottom 264.567px)"
+[FAIL] test unit (computed): mm - circle(at right 80mm top 50%)
+  assert_equals: expected "circle(at calc(100% - 302.362px) 50%)" but got "circle(at right 302.362px top 50%)"
+[FAIL] test unit (computed): mm - circle(at right 80mm bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 302.362px) 30%)" but got "circle(at right 302.362px top 30%)"
+[FAIL] test unit (computed): mm - circle(at right 80mm bottom 70mm)
+  assert_equals: expected "circle(at calc(100% - 302.362px) calc(100% - 264.567px))" but got "circle(at right 302.362px bottom 264.567px)"
+[PASS] test unit (computed): in - circle(at 50in)
+[PASS] test unit (computed): in - circle(at 50% 50in)
+[PASS] test unit (computed): in - circle(at 50in 50%)
+[PASS] test unit (computed): in - circle(at 50in 50in)
+[PASS] test unit (computed): in - circle(at left 50in)
+[PASS] test unit (computed): in - circle(at 50in top)
+[PASS] test unit (computed): in - circle(at right 80in)
+[PASS] test unit (computed): in - circle(at 70in bottom)
+[PASS] test unit (computed): in - circle(at center 60in)
+[PASS] test unit (computed): in - circle(at 60in center)
+[PASS] test unit (computed): in - circle(at left 50% top 50in)
+[FAIL] test unit (computed): in - circle(at left 50% bottom 70in)
+  assert_equals: expected "circle(at 50% calc(100% - 6720px))" but got "circle(at left 50% bottom 6720px)"
+[PASS] test unit (computed): in - circle(at left 50in top 50%)
+[PASS] test unit (computed): in - circle(at left 50in top 50in)
+[PASS] test unit (computed): in - circle(at left 50in bottom 70%)
+[PASS] test unit (computed): in - circle(at top 50% left 50in)
+[FAIL] test unit (computed): in - circle(at top 50% right 80in)
+  assert_equals: expected "circle(at calc(100% - 7680px) 50%)" but got "circle(at right 7680px top 50%)"
+[PASS] test unit (computed): in - circle(at top 50in left 50%)
+[PASS] test unit (computed): in - circle(at top 50in left 50in)
+[PASS] test unit (computed): in - circle(at top 50in right 80%)
+[PASS] test unit (computed): in - circle(at bottom 70% left 50in)
+[FAIL] test unit (computed): in - circle(at bottom 70% right 80in)
+  assert_equals: expected "circle(at calc(100% - 7680px) 30%)" but got "circle(at right 7680px top 30%)"
+[FAIL] test unit (computed): in - circle(at bottom 70in left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 6720px))" but got "circle(at left 50% bottom 6720px)"
+[FAIL] test unit (computed): in - circle(at bottom 70in right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 6720px))" but got "circle(at left 50% bottom 6720px)"
+[FAIL] test unit (computed): in - circle(at bottom 70in right 80in)
+  assert_equals: expected "circle(at calc(100% - 7680px) calc(100% - 6720px))" but got "circle(at right 7680px bottom 6720px)"
+[PASS] test unit (computed): in - circle(at right 80% top 50in)
+[FAIL] test unit (computed): in - circle(at right 80% bottom 70in)
+  assert_equals: expected "circle(at 20% calc(100% - 6720px))" but got "circle(at left 20% bottom 6720px)"
+[FAIL] test unit (computed): in - circle(at right 80in top 50%)
+  assert_equals: expected "circle(at calc(100% - 7680px) 50%)" but got "circle(at right 7680px top 50%)"
+[FAIL] test unit (computed): in - circle(at right 80in bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 7680px) 30%)" but got "circle(at right 7680px top 30%)"
+[FAIL] test unit (computed): in - circle(at right 80in bottom 70in)
+  assert_equals: expected "circle(at calc(100% - 7680px) calc(100% - 6720px))" but got "circle(at right 7680px bottom 6720px)"
+[PASS] test unit (computed): pt - circle(at 50pt)
+[PASS] test unit (computed): pt - circle(at 50% 50pt)
+[PASS] test unit (computed): pt - circle(at 50pt 50%)
+[PASS] test unit (computed): pt - circle(at 50pt 50pt)
+[PASS] test unit (computed): pt - circle(at left 50pt)
+[PASS] test unit (computed): pt - circle(at 50pt top)
+[PASS] test unit (computed): pt - circle(at right 80pt)
+[PASS] test unit (computed): pt - circle(at 70pt bottom)
+[PASS] test unit (computed): pt - circle(at center 60pt)
+[PASS] test unit (computed): pt - circle(at 60pt center)
+[PASS] test unit (computed): pt - circle(at left 50% top 50pt)
+[FAIL] test unit (computed): pt - circle(at left 50% bottom 70pt)
+  assert_equals: expected "circle(at 50% calc(100% - 93.3333px))" but got "circle(at left 50% bottom 93.3333px)"
+[PASS] test unit (computed): pt - circle(at left 50pt top 50%)
+[PASS] test unit (computed): pt - circle(at left 50pt top 50pt)
+[PASS] test unit (computed): pt - circle(at left 50pt bottom 70%)
+[PASS] test unit (computed): pt - circle(at top 50% left 50pt)
+[FAIL] test unit (computed): pt - circle(at top 50% right 80pt)
+  assert_equals: expected "circle(at calc(100% - 106.667px) 50%)" but got "circle(at right 106.667px top 50%)"
+[PASS] test unit (computed): pt - circle(at top 50pt left 50%)
+[PASS] test unit (computed): pt - circle(at top 50pt left 50pt)
+[PASS] test unit (computed): pt - circle(at top 50pt right 80%)
+[PASS] test unit (computed): pt - circle(at bottom 70% left 50pt)
+[FAIL] test unit (computed): pt - circle(at bottom 70% right 80pt)
+  assert_equals: expected "circle(at calc(100% - 106.667px) 30%)" but got "circle(at right 106.667px top 30%)"
+[FAIL] test unit (computed): pt - circle(at bottom 70pt left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 93.3333px))" but got "circle(at left 50% bottom 93.3333px)"
+[FAIL] test unit (computed): pt - circle(at bottom 70pt right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 93.3333px))" but got "circle(at left 50% bottom 93.3333px)"
+[FAIL] test unit (computed): pt - circle(at bottom 70pt right 80pt)
+  assert_equals: expected "circle(at calc(100% - 106.667px) calc(100% - 93.3333px))" but got "circle(at right 106.667px bottom 93.3333px)"
+[PASS] test unit (computed): pt - circle(at right 80% top 50pt)
+[FAIL] test unit (computed): pt - circle(at right 80% bottom 70pt)
+  assert_equals: expected "circle(at 20% calc(100% - 93.3333px))" but got "circle(at left 20% bottom 93.3333px)"
+[FAIL] test unit (computed): pt - circle(at right 80pt top 50%)
+  assert_equals: expected "circle(at calc(100% - 106.667px) 50%)" but got "circle(at right 106.667px top 50%)"
+[FAIL] test unit (computed): pt - circle(at right 80pt bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 106.667px) 30%)" but got "circle(at right 106.667px top 30%)"
+[FAIL] test unit (computed): pt - circle(at right 80pt bottom 70pt)
+  assert_equals: expected "circle(at calc(100% - 106.667px) calc(100% - 93.3333px))" but got "circle(at right 106.667px bottom 93.3333px)"
+[PASS] test unit (computed): pc - circle(at 50pc)
+[PASS] test unit (computed): pc - circle(at 50% 50pc)
+[PASS] test unit (computed): pc - circle(at 50pc 50%)
+[PASS] test unit (computed): pc - circle(at 50pc 50pc)
+[PASS] test unit (computed): pc - circle(at left 50pc)
+[PASS] test unit (computed): pc - circle(at 50pc top)
+[PASS] test unit (computed): pc - circle(at right 80pc)
+[PASS] test unit (computed): pc - circle(at 70pc bottom)
+[PASS] test unit (computed): pc - circle(at center 60pc)
+[PASS] test unit (computed): pc - circle(at 60pc center)
+[PASS] test unit (computed): pc - circle(at left 50% top 50pc)
+[FAIL] test unit (computed): pc - circle(at left 50% bottom 70pc)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 1120px)"
+[PASS] test unit (computed): pc - circle(at left 50pc top 50%)
+[PASS] test unit (computed): pc - circle(at left 50pc top 50pc)
+[PASS] test unit (computed): pc - circle(at left 50pc bottom 70%)
+[PASS] test unit (computed): pc - circle(at top 50% left 50pc)
+[FAIL] test unit (computed): pc - circle(at top 50% right 80pc)
+  assert_equals: expected "circle(at calc(100% - 1280px) 50%)" but got "circle(at right 1280px top 50%)"
+[PASS] test unit (computed): pc - circle(at top 50pc left 50%)
+[PASS] test unit (computed): pc - circle(at top 50pc left 50pc)
+[PASS] test unit (computed): pc - circle(at top 50pc right 80%)
+[PASS] test unit (computed): pc - circle(at bottom 70% left 50pc)
+[FAIL] test unit (computed): pc - circle(at bottom 70% right 80pc)
+  assert_equals: expected "circle(at calc(100% - 1280px) 30%)" but got "circle(at right 1280px top 30%)"
+[FAIL] test unit (computed): pc - circle(at bottom 70pc left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 1120px)"
+[FAIL] test unit (computed): pc - circle(at bottom 70pc right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 1120px)"
+[FAIL] test unit (computed): pc - circle(at bottom 70pc right 80pc)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(100% - 1120px))" but got "circle(at right 1280px bottom 1120px)"
+[PASS] test unit (computed): pc - circle(at right 80% top 50pc)
+[FAIL] test unit (computed): pc - circle(at right 80% bottom 70pc)
+  assert_equals: expected "circle(at 20% calc(100% - 1120px))" but got "circle(at left 20% bottom 1120px)"
+[FAIL] test unit (computed): pc - circle(at right 80pc top 50%)
+  assert_equals: expected "circle(at calc(100% - 1280px) 50%)" but got "circle(at right 1280px top 50%)"
+[FAIL] test unit (computed): pc - circle(at right 80pc bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 1280px) 30%)" but got "circle(at right 1280px top 30%)"
+[FAIL] test unit (computed): pc - circle(at right 80pc bottom 70pc)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(100% - 1120px))" but got "circle(at right 1280px bottom 1120px)"
+[PASS] test unit (computed): em - circle(at 50em)
+[PASS] test unit (computed): em - circle(at 50% 50em)
+[PASS] test unit (computed): em - circle(at 50em 50%)
+[PASS] test unit (computed): em - circle(at 50em 50em)
+[PASS] test unit (computed): em - circle(at left 50em)
+[PASS] test unit (computed): em - circle(at 50em top)
+[PASS] test unit (computed): em - circle(at right 80em)
+[PASS] test unit (computed): em - circle(at 70em bottom)
+[PASS] test unit (computed): em - circle(at center 60em)
+[PASS] test unit (computed): em - circle(at 60em center)
+[PASS] test unit (computed): em - circle(at left 50% top 50em)
+[FAIL] test unit (computed): em - circle(at left 50% bottom 70em)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 1120px)"
+[PASS] test unit (computed): em - circle(at left 50em top 50%)
+[PASS] test unit (computed): em - circle(at left 50em top 50em)
+[PASS] test unit (computed): em - circle(at left 50em bottom 70%)
+[PASS] test unit (computed): em - circle(at top 50% left 50em)
+[FAIL] test unit (computed): em - circle(at top 50% right 80em)
+  assert_equals: expected "circle(at calc(100% - 1280px) 50%)" but got "circle(at right 1280px top 50%)"
+[PASS] test unit (computed): em - circle(at top 50em left 50%)
+[PASS] test unit (computed): em - circle(at top 50em left 50em)
+[PASS] test unit (computed): em - circle(at top 50em right 80%)
+[PASS] test unit (computed): em - circle(at bottom 70% left 50em)
+[FAIL] test unit (computed): em - circle(at bottom 70% right 80em)
+  assert_equals: expected "circle(at calc(100% - 1280px) 30%)" but got "circle(at right 1280px top 30%)"
+[FAIL] test unit (computed): em - circle(at bottom 70em left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 1120px)"
+[FAIL] test unit (computed): em - circle(at bottom 70em right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 1120px)"
+[FAIL] test unit (computed): em - circle(at bottom 70em right 80em)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(100% - 1120px))" but got "circle(at right 1280px bottom 1120px)"
+[PASS] test unit (computed): em - circle(at right 80% top 50em)
+[FAIL] test unit (computed): em - circle(at right 80% bottom 70em)
+  assert_equals: expected "circle(at 20% calc(100% - 1120px))" but got "circle(at left 20% bottom 1120px)"
+[FAIL] test unit (computed): em - circle(at right 80em top 50%)
+  assert_equals: expected "circle(at calc(100% - 1280px) 50%)" but got "circle(at right 1280px top 50%)"
+[FAIL] test unit (computed): em - circle(at right 80em bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 1280px) 30%)" but got "circle(at right 1280px top 30%)"
+[FAIL] test unit (computed): em - circle(at right 80em bottom 70em)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(100% - 1120px))" but got "circle(at right 1280px bottom 1120px)"
+[FAIL] test unit (computed): ex - circle(at 50ex)
+  assert_equals: expected "circle(at 640px 50%)" but got "circle(at 400px 50%)"
+[FAIL] test unit (computed): ex - circle(at 50% 50ex)
+  assert_equals: expected "circle(at 50% 640px)" but got "circle(at 50% 400px)"
+[FAIL] test unit (computed): ex - circle(at 50ex 50%)
+  assert_equals: expected "circle(at 640px 50%)" but got "circle(at 400px 50%)"
+[FAIL] test unit (computed): ex - circle(at 50ex 50ex)
+  assert_equals: expected "circle(at 640px 640px)" but got "circle(at 400px 400px)"
+[FAIL] test unit (computed): ex - circle(at left 50ex)
+  assert_equals: expected "circle(at 0% 640px)" but got "circle(at 0% 400px)"
+[FAIL] test unit (computed): ex - circle(at 50ex top)
+  assert_equals: expected "circle(at 640px 0%)" but got "circle(at 400px 0%)"
+[FAIL] test unit (computed): ex - circle(at right 80ex)
+  assert_equals: expected "circle(at 100% 1024px)" but got "circle(at 100% 640px)"
+[FAIL] test unit (computed): ex - circle(at 70ex bottom)
+  assert_equals: expected "circle(at 896px 100%)" but got "circle(at 560px 100%)"
+[FAIL] test unit (computed): ex - circle(at center 60ex)
+  assert_equals: expected "circle(at 50% 768px)" but got "circle(at 50% 480px)"
+[FAIL] test unit (computed): ex - circle(at 60ex center)
+  assert_equals: expected "circle(at 768px 50%)" but got "circle(at 480px 50%)"
+[FAIL] test unit (computed): ex - circle(at left 50% top 50ex)
+  assert_equals: expected "circle(at 50% 640px)" but got "circle(at 50% 400px)"
+[FAIL] test unit (computed): ex - circle(at left 50% bottom 70ex)
+  assert_equals: expected "circle(at 50% calc(100% - 896px))" but got "circle(at left 50% bottom 560px)"
+[FAIL] test unit (computed): ex - circle(at left 50ex top 50%)
+  assert_equals: expected "circle(at 640px 50%)" but got "circle(at 400px 50%)"
+[FAIL] test unit (computed): ex - circle(at left 50ex top 50ex)
+  assert_equals: expected "circle(at 640px 640px)" but got "circle(at 400px 400px)"
+[FAIL] test unit (computed): ex - circle(at left 50ex bottom 70%)
+  assert_equals: expected "circle(at 640px 30%)" but got "circle(at 400px 30%)"
+[FAIL] test unit (computed): ex - circle(at top 50% left 50ex)
+  assert_equals: expected "circle(at 640px 50%)" but got "circle(at 400px 50%)"
+[FAIL] test unit (computed): ex - circle(at top 50% right 80ex)
+  assert_equals: expected "circle(at calc(100% - 1024px) 50%)" but got "circle(at right 640px top 50%)"
+[FAIL] test unit (computed): ex - circle(at top 50ex left 50%)
+  assert_equals: expected "circle(at 50% 640px)" but got "circle(at 50% 400px)"
+[FAIL] test unit (computed): ex - circle(at top 50ex left 50ex)
+  assert_equals: expected "circle(at 640px 640px)" but got "circle(at 400px 400px)"
+[FAIL] test unit (computed): ex - circle(at top 50ex right 80%)
+  assert_equals: expected "circle(at 20% 640px)" but got "circle(at 20% 400px)"
+[FAIL] test unit (computed): ex - circle(at bottom 70% left 50ex)
+  assert_equals: expected "circle(at 640px 30%)" but got "circle(at 400px 30%)"
+[FAIL] test unit (computed): ex - circle(at bottom 70% right 80ex)
+  assert_equals: expected "circle(at calc(100% - 1024px) 30%)" but got "circle(at right 640px top 30%)"
+[FAIL] test unit (computed): ex - circle(at bottom 70ex left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 896px))" but got "circle(at left 50% bottom 560px)"
+[FAIL] test unit (computed): ex - circle(at bottom 70ex right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 896px))" but got "circle(at left 50% bottom 560px)"
+[FAIL] test unit (computed): ex - circle(at bottom 70ex right 80ex)
+  assert_equals: expected "circle(at calc(100% - 1024px) calc(100% - 896px))" but got "circle(at right 640px bottom 560px)"
+[FAIL] test unit (computed): ex - circle(at right 80% top 50ex)
+  assert_equals: expected "circle(at 20% 640px)" but got "circle(at 20% 400px)"
+[FAIL] test unit (computed): ex - circle(at right 80% bottom 70ex)
+  assert_equals: expected "circle(at 20% calc(100% - 896px))" but got "circle(at left 20% bottom 560px)"
+[FAIL] test unit (computed): ex - circle(at right 80ex top 50%)
+  assert_equals: expected "circle(at calc(100% - 1024px) 50%)" but got "circle(at right 640px top 50%)"
+[FAIL] test unit (computed): ex - circle(at right 80ex bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 1024px) 30%)" but got "circle(at right 640px top 30%)"
+[FAIL] test unit (computed): ex - circle(at right 80ex bottom 70ex)
+  assert_equals: expected "circle(at calc(100% - 1024px) calc(100% - 896px))" but got "circle(at right 640px bottom 560px)"
+[FAIL] test unit (computed): ch - circle(at 50ch)
+  assert_equals: expected "circle(at 800px 50%)" but got "circle(at 400px 50%)"
+[FAIL] test unit (computed): ch - circle(at 50% 50ch)
+  assert_equals: expected "circle(at 50% 800px)" but got "circle(at 50% 400px)"
+[FAIL] test unit (computed): ch - circle(at 50ch 50%)
+  assert_equals: expected "circle(at 800px 50%)" but got "circle(at 400px 50%)"
+[FAIL] test unit (computed): ch - circle(at 50ch 50ch)
+  assert_equals: expected "circle(at 800px 800px)" but got "circle(at 400px 400px)"
+[FAIL] test unit (computed): ch - circle(at left 50ch)
+  assert_equals: expected "circle(at 0% 800px)" but got "circle(at 0% 400px)"
+[FAIL] test unit (computed): ch - circle(at 50ch top)
+  assert_equals: expected "circle(at 800px 0%)" but got "circle(at 400px 0%)"
+[FAIL] test unit (computed): ch - circle(at right 80ch)
+  assert_equals: expected "circle(at 100% 1280px)" but got "circle(at 100% 640px)"
+[FAIL] test unit (computed): ch - circle(at 70ch bottom)
+  assert_equals: expected "circle(at 1120px 100%)" but got "circle(at 560px 100%)"
+[FAIL] test unit (computed): ch - circle(at center 60ch)
+  assert_equals: expected "circle(at 50% 960px)" but got "circle(at 50% 480px)"
+[FAIL] test unit (computed): ch - circle(at 60ch center)
+  assert_equals: expected "circle(at 960px 50%)" but got "circle(at 480px 50%)"
+[FAIL] test unit (computed): ch - circle(at left 50% top 50ch)
+  assert_equals: expected "circle(at 50% 800px)" but got "circle(at 50% 400px)"
+[FAIL] test unit (computed): ch - circle(at left 50% bottom 70ch)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 560px)"
+[FAIL] test unit (computed): ch - circle(at left 50ch top 50%)
+  assert_equals: expected "circle(at 800px 50%)" but got "circle(at 400px 50%)"
+[FAIL] test unit (computed): ch - circle(at left 50ch top 50ch)
+  assert_equals: expected "circle(at 800px 800px)" but got "circle(at 400px 400px)"
+[FAIL] test unit (computed): ch - circle(at left 50ch bottom 70%)
+  assert_equals: expected "circle(at 800px 30%)" but got "circle(at 400px 30%)"
+[FAIL] test unit (computed): ch - circle(at top 50% left 50ch)
+  assert_equals: expected "circle(at 800px 50%)" but got "circle(at 400px 50%)"
+[FAIL] test unit (computed): ch - circle(at top 50% right 80ch)
+  assert_equals: expected "circle(at calc(100% - 1280px) 50%)" but got "circle(at right 640px top 50%)"
+[FAIL] test unit (computed): ch - circle(at top 50ch left 50%)
+  assert_equals: expected "circle(at 50% 800px)" but got "circle(at 50% 400px)"
+[FAIL] test unit (computed): ch - circle(at top 50ch left 50ch)
+  assert_equals: expected "circle(at 800px 800px)" but got "circle(at 400px 400px)"
+[FAIL] test unit (computed): ch - circle(at top 50ch right 80%)
+  assert_equals: expected "circle(at 20% 800px)" but got "circle(at 20% 400px)"
+[FAIL] test unit (computed): ch - circle(at bottom 70% left 50ch)
+  assert_equals: expected "circle(at 800px 30%)" but got "circle(at 400px 30%)"
+[FAIL] test unit (computed): ch - circle(at bottom 70% right 80ch)
+  assert_equals: expected "circle(at calc(100% - 1280px) 30%)" but got "circle(at right 640px top 30%)"
+[FAIL] test unit (computed): ch - circle(at bottom 70ch left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 560px)"
+[FAIL] test unit (computed): ch - circle(at bottom 70ch right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 560px)"
+[FAIL] test unit (computed): ch - circle(at bottom 70ch right 80ch)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(100% - 1120px))" but got "circle(at right 640px bottom 560px)"
+[FAIL] test unit (computed): ch - circle(at right 80% top 50ch)
+  assert_equals: expected "circle(at 20% 800px)" but got "circle(at 20% 400px)"
+[FAIL] test unit (computed): ch - circle(at right 80% bottom 70ch)
+  assert_equals: expected "circle(at 20% calc(100% - 1120px))" but got "circle(at left 20% bottom 560px)"
+[FAIL] test unit (computed): ch - circle(at right 80ch top 50%)
+  assert_equals: expected "circle(at calc(100% - 1280px) 50%)" but got "circle(at right 640px top 50%)"
+[FAIL] test unit (computed): ch - circle(at right 80ch bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 1280px) 30%)" but got "circle(at right 640px top 30%)"
+[FAIL] test unit (computed): ch - circle(at right 80ch bottom 70ch)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(100% - 1120px))" but got "circle(at right 640px bottom 560px)"
+[PASS] test unit (computed): rem - circle(at 50rem)
+[PASS] test unit (computed): rem - circle(at 50% 50rem)
+[PASS] test unit (computed): rem - circle(at 50rem 50%)
+[PASS] test unit (computed): rem - circle(at 50rem 50rem)
+[PASS] test unit (computed): rem - circle(at left 50rem)
+[PASS] test unit (computed): rem - circle(at 50rem top)
+[PASS] test unit (computed): rem - circle(at right 80rem)
+[PASS] test unit (computed): rem - circle(at 70rem bottom)
+[PASS] test unit (computed): rem - circle(at center 60rem)
+[PASS] test unit (computed): rem - circle(at 60rem center)
+[PASS] test unit (computed): rem - circle(at left 50% top 50rem)
+[FAIL] test unit (computed): rem - circle(at left 50% bottom 70rem)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 1120px)"
+[PASS] test unit (computed): rem - circle(at left 50rem top 50%)
+[PASS] test unit (computed): rem - circle(at left 50rem top 50rem)
+[PASS] test unit (computed): rem - circle(at left 50rem bottom 70%)
+[PASS] test unit (computed): rem - circle(at top 50% left 50rem)
+[FAIL] test unit (computed): rem - circle(at top 50% right 80rem)
+  assert_equals: expected "circle(at calc(100% - 1280px) 50%)" but got "circle(at right 1280px top 50%)"
+[PASS] test unit (computed): rem - circle(at top 50rem left 50%)
+[PASS] test unit (computed): rem - circle(at top 50rem left 50rem)
+[PASS] test unit (computed): rem - circle(at top 50rem right 80%)
+[PASS] test unit (computed): rem - circle(at bottom 70% left 50rem)
+[FAIL] test unit (computed): rem - circle(at bottom 70% right 80rem)
+  assert_equals: expected "circle(at calc(100% - 1280px) 30%)" but got "circle(at right 1280px top 30%)"
+[FAIL] test unit (computed): rem - circle(at bottom 70rem left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 1120px)"
+[FAIL] test unit (computed): rem - circle(at bottom 70rem right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 1120px))" but got "circle(at left 50% bottom 1120px)"
+[FAIL] test unit (computed): rem - circle(at bottom 70rem right 80rem)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(100% - 1120px))" but got "circle(at right 1280px bottom 1120px)"
+[PASS] test unit (computed): rem - circle(at right 80% top 50rem)
+[FAIL] test unit (computed): rem - circle(at right 80% bottom 70rem)
+  assert_equals: expected "circle(at 20% calc(100% - 1120px))" but got "circle(at left 20% bottom 1120px)"
+[FAIL] test unit (computed): rem - circle(at right 80rem top 50%)
+  assert_equals: expected "circle(at calc(100% - 1280px) 50%)" but got "circle(at right 1280px top 50%)"
+[FAIL] test unit (computed): rem - circle(at right 80rem bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 1280px) 30%)" but got "circle(at right 1280px top 30%)"
+[FAIL] test unit (computed): rem - circle(at right 80rem bottom 70rem)
+  assert_equals: expected "circle(at calc(100% - 1280px) calc(100% - 1120px))" but got "circle(at right 1280px bottom 1120px)"
+[PASS] test unit (computed): vw - circle(at 50vw)
+[PASS] test unit (computed): vw - circle(at 50% 50vw)
+[PASS] test unit (computed): vw - circle(at 50vw 50%)
+[PASS] test unit (computed): vw - circle(at 50vw 50vw)
+[PASS] test unit (computed): vw - circle(at left 50vw)
+[PASS] test unit (computed): vw - circle(at 50vw top)
+[PASS] test unit (computed): vw - circle(at right 80vw)
+[PASS] test unit (computed): vw - circle(at 70vw bottom)
+[PASS] test unit (computed): vw - circle(at center 60vw)
+[PASS] test unit (computed): vw - circle(at 60vw center)
+[PASS] test unit (computed): vw - circle(at left 50% top 50vw)
+[FAIL] test unit (computed): vw - circle(at left 50% bottom 70vw)
+  assert_equals: expected "circle(at 50% calc(100% - 560px))" but got "circle(at left 50% bottom 560px)"
+[PASS] test unit (computed): vw - circle(at left 50vw top 50%)
+[PASS] test unit (computed): vw - circle(at left 50vw top 50vw)
+[PASS] test unit (computed): vw - circle(at left 50vw bottom 70%)
+[PASS] test unit (computed): vw - circle(at top 50% left 50vw)
+[FAIL] test unit (computed): vw - circle(at top 50% right 80vw)
+  assert_equals: expected "circle(at calc(100% - 640px) 50%)" but got "circle(at right 640px top 50%)"
+[PASS] test unit (computed): vw - circle(at top 50vw left 50%)
+[PASS] test unit (computed): vw - circle(at top 50vw left 50vw)
+[PASS] test unit (computed): vw - circle(at top 50vw right 80%)
+[PASS] test unit (computed): vw - circle(at bottom 70% left 50vw)
+[FAIL] test unit (computed): vw - circle(at bottom 70% right 80vw)
+  assert_equals: expected "circle(at calc(100% - 640px) 30%)" but got "circle(at right 640px top 30%)"
+[FAIL] test unit (computed): vw - circle(at bottom 70vw left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 560px))" but got "circle(at left 50% bottom 560px)"
+[FAIL] test unit (computed): vw - circle(at bottom 70vw right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 560px))" but got "circle(at left 50% bottom 560px)"
+[FAIL] test unit (computed): vw - circle(at bottom 70vw right 80vw)
+  assert_equals: expected "circle(at calc(100% - 640px) calc(100% - 560px))" but got "circle(at right 640px bottom 560px)"
+[PASS] test unit (computed): vw - circle(at right 80% top 50vw)
+[FAIL] test unit (computed): vw - circle(at right 80% bottom 70vw)
+  assert_equals: expected "circle(at 20% calc(100% - 560px))" but got "circle(at left 20% bottom 560px)"
+[FAIL] test unit (computed): vw - circle(at right 80vw top 50%)
+  assert_equals: expected "circle(at calc(100% - 640px) 50%)" but got "circle(at right 640px top 50%)"
+[FAIL] test unit (computed): vw - circle(at right 80vw bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 640px) 30%)" but got "circle(at right 640px top 30%)"
+[FAIL] test unit (computed): vw - circle(at right 80vw bottom 70vw)
+  assert_equals: expected "circle(at calc(100% - 640px) calc(100% - 560px))" but got "circle(at right 640px bottom 560px)"
+[PASS] test unit (computed): vh - circle(at 50vh)
+[PASS] test unit (computed): vh - circle(at 50% 50vh)
+[PASS] test unit (computed): vh - circle(at 50vh 50%)
+[PASS] test unit (computed): vh - circle(at 50vh 50vh)
+[PASS] test unit (computed): vh - circle(at left 50vh)
+[PASS] test unit (computed): vh - circle(at 50vh top)
+[PASS] test unit (computed): vh - circle(at right 80vh)
+[PASS] test unit (computed): vh - circle(at 70vh bottom)
+[PASS] test unit (computed): vh - circle(at center 60vh)
+[PASS] test unit (computed): vh - circle(at 60vh center)
+[PASS] test unit (computed): vh - circle(at left 50% top 50vh)
+[FAIL] test unit (computed): vh - circle(at left 50% bottom 70vh)
+  assert_equals: expected "circle(at 50% calc(100% - 420px))" but got "circle(at left 50% bottom 420px)"
+[PASS] test unit (computed): vh - circle(at left 50vh top 50%)
+[PASS] test unit (computed): vh - circle(at left 50vh top 50vh)
+[PASS] test unit (computed): vh - circle(at left 50vh bottom 70%)
+[PASS] test unit (computed): vh - circle(at top 50% left 50vh)
+[FAIL] test unit (computed): vh - circle(at top 50% right 80vh)
+  assert_equals: expected "circle(at calc(100% - 480px) 50%)" but got "circle(at right 480px top 50%)"
+[PASS] test unit (computed): vh - circle(at top 50vh left 50%)
+[PASS] test unit (computed): vh - circle(at top 50vh left 50vh)
+[PASS] test unit (computed): vh - circle(at top 50vh right 80%)
+[PASS] test unit (computed): vh - circle(at bottom 70% left 50vh)
+[FAIL] test unit (computed): vh - circle(at bottom 70% right 80vh)
+  assert_equals: expected "circle(at calc(100% - 480px) 30%)" but got "circle(at right 480px top 30%)"
+[FAIL] test unit (computed): vh - circle(at bottom 70vh left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 420px))" but got "circle(at left 50% bottom 420px)"
+[FAIL] test unit (computed): vh - circle(at bottom 70vh right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 420px))" but got "circle(at left 50% bottom 420px)"
+[FAIL] test unit (computed): vh - circle(at bottom 70vh right 80vh)
+  assert_equals: expected "circle(at calc(100% - 480px) calc(100% - 420px))" but got "circle(at right 480px bottom 420px)"
+[PASS] test unit (computed): vh - circle(at right 80% top 50vh)
+[FAIL] test unit (computed): vh - circle(at right 80% bottom 70vh)
+  assert_equals: expected "circle(at 20% calc(100% - 420px))" but got "circle(at left 20% bottom 420px)"
+[FAIL] test unit (computed): vh - circle(at right 80vh top 50%)
+  assert_equals: expected "circle(at calc(100% - 480px) 50%)" but got "circle(at right 480px top 50%)"
+[FAIL] test unit (computed): vh - circle(at right 80vh bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 480px) 30%)" but got "circle(at right 480px top 30%)"
+[FAIL] test unit (computed): vh - circle(at right 80vh bottom 70vh)
+  assert_equals: expected "circle(at calc(100% - 480px) calc(100% - 420px))" but got "circle(at right 480px bottom 420px)"
+[PASS] test unit (computed): vmin - circle(at 50vmin)
+[PASS] test unit (computed): vmin - circle(at 50% 50vmin)
+[PASS] test unit (computed): vmin - circle(at 50vmin 50%)
+[PASS] test unit (computed): vmin - circle(at 50vmin 50vmin)
+[PASS] test unit (computed): vmin - circle(at left 50vmin)
+[PASS] test unit (computed): vmin - circle(at 50vmin top)
+[PASS] test unit (computed): vmin - circle(at right 80vmin)
+[PASS] test unit (computed): vmin - circle(at 70vmin bottom)
+[PASS] test unit (computed): vmin - circle(at center 60vmin)
+[PASS] test unit (computed): vmin - circle(at 60vmin center)
+[PASS] test unit (computed): vmin - circle(at left 50% top 50vmin)
+[FAIL] test unit (computed): vmin - circle(at left 50% bottom 70vmin)
+  assert_equals: expected "circle(at 50% calc(100% - 420px))" but got "circle(at left 50% bottom 420px)"
+[PASS] test unit (computed): vmin - circle(at left 50vmin top 50%)
+[PASS] test unit (computed): vmin - circle(at left 50vmin top 50vmin)
+[PASS] test unit (computed): vmin - circle(at left 50vmin bottom 70%)
+[PASS] test unit (computed): vmin - circle(at top 50% left 50vmin)
+[FAIL] test unit (computed): vmin - circle(at top 50% right 80vmin)
+  assert_equals: expected "circle(at calc(100% - 480px) 50%)" but got "circle(at right 480px top 50%)"
+[PASS] test unit (computed): vmin - circle(at top 50vmin left 50%)
+[PASS] test unit (computed): vmin - circle(at top 50vmin left 50vmin)
+[PASS] test unit (computed): vmin - circle(at top 50vmin right 80%)
+[PASS] test unit (computed): vmin - circle(at bottom 70% left 50vmin)
+[FAIL] test unit (computed): vmin - circle(at bottom 70% right 80vmin)
+  assert_equals: expected "circle(at calc(100% - 480px) 30%)" but got "circle(at right 480px top 30%)"
+[FAIL] test unit (computed): vmin - circle(at bottom 70vmin left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 420px))" but got "circle(at left 50% bottom 420px)"
+[FAIL] test unit (computed): vmin - circle(at bottom 70vmin right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 420px))" but got "circle(at left 50% bottom 420px)"
+[FAIL] test unit (computed): vmin - circle(at bottom 70vmin right 80vmin)
+  assert_equals: expected "circle(at calc(100% - 480px) calc(100% - 420px))" but got "circle(at right 480px bottom 420px)"
+[PASS] test unit (computed): vmin - circle(at right 80% top 50vmin)
+[FAIL] test unit (computed): vmin - circle(at right 80% bottom 70vmin)
+  assert_equals: expected "circle(at 20% calc(100% - 420px))" but got "circle(at left 20% bottom 420px)"
+[FAIL] test unit (computed): vmin - circle(at right 80vmin top 50%)
+  assert_equals: expected "circle(at calc(100% - 480px) 50%)" but got "circle(at right 480px top 50%)"
+[FAIL] test unit (computed): vmin - circle(at right 80vmin bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 480px) 30%)" but got "circle(at right 480px top 30%)"
+[FAIL] test unit (computed): vmin - circle(at right 80vmin bottom 70vmin)
+  assert_equals: expected "circle(at calc(100% - 480px) calc(100% - 420px))" but got "circle(at right 480px bottom 420px)"
+[PASS] test unit (computed): vmax - circle(at 50vmax)
+[PASS] test unit (computed): vmax - circle(at 50% 50vmax)
+[PASS] test unit (computed): vmax - circle(at 50vmax 50%)
+[PASS] test unit (computed): vmax - circle(at 50vmax 50vmax)
+[PASS] test unit (computed): vmax - circle(at left 50vmax)
+[PASS] test unit (computed): vmax - circle(at 50vmax top)
+[PASS] test unit (computed): vmax - circle(at right 80vmax)
+[PASS] test unit (computed): vmax - circle(at 70vmax bottom)
+[PASS] test unit (computed): vmax - circle(at center 60vmax)
+[PASS] test unit (computed): vmax - circle(at 60vmax center)
+[PASS] test unit (computed): vmax - circle(at left 50% top 50vmax)
+[FAIL] test unit (computed): vmax - circle(at left 50% bottom 70vmax)
+  assert_equals: expected "circle(at 50% calc(100% - 560px))" but got "circle(at left 50% bottom 560px)"
+[PASS] test unit (computed): vmax - circle(at left 50vmax top 50%)
+[PASS] test unit (computed): vmax - circle(at left 50vmax top 50vmax)
+[PASS] test unit (computed): vmax - circle(at left 50vmax bottom 70%)
+[PASS] test unit (computed): vmax - circle(at top 50% left 50vmax)
+[FAIL] test unit (computed): vmax - circle(at top 50% right 80vmax)
+  assert_equals: expected "circle(at calc(100% - 640px) 50%)" but got "circle(at right 640px top 50%)"
+[PASS] test unit (computed): vmax - circle(at top 50vmax left 50%)
+[PASS] test unit (computed): vmax - circle(at top 50vmax left 50vmax)
+[PASS] test unit (computed): vmax - circle(at top 50vmax right 80%)
+[PASS] test unit (computed): vmax - circle(at bottom 70% left 50vmax)
+[FAIL] test unit (computed): vmax - circle(at bottom 70% right 80vmax)
+  assert_equals: expected "circle(at calc(100% - 640px) 30%)" but got "circle(at right 640px top 30%)"
+[FAIL] test unit (computed): vmax - circle(at bottom 70vmax left 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 560px))" but got "circle(at left 50% bottom 560px)"
+[FAIL] test unit (computed): vmax - circle(at bottom 70vmax right 50%)
+  assert_equals: expected "circle(at 50% calc(100% - 560px))" but got "circle(at left 50% bottom 560px)"
+[FAIL] test unit (computed): vmax - circle(at bottom 70vmax right 80vmax)
+  assert_equals: expected "circle(at calc(100% - 640px) calc(100% - 560px))" but got "circle(at right 640px bottom 560px)"
+[PASS] test unit (computed): vmax - circle(at right 80% top 50vmax)
+[FAIL] test unit (computed): vmax - circle(at right 80% bottom 70vmax)
+  assert_equals: expected "circle(at 20% calc(100% - 560px))" but got "circle(at left 20% bottom 560px)"
+[FAIL] test unit (computed): vmax - circle(at right 80vmax top 50%)
+  assert_equals: expected "circle(at calc(100% - 640px) 50%)" but got "circle(at right 640px top 50%)"
+[FAIL] test unit (computed): vmax - circle(at right 80vmax bottom 70%)
+  assert_equals: expected "circle(at calc(100% - 640px) 30%)" but got "circle(at right 640px top 30%)"
+[FAIL] test unit (computed): vmax - circle(at right 80vmax bottom 70vmax)
+  assert_equals: expected "circle(at calc(100% - 640px) calc(100% - 560px))" but got "circle(at right 640px bottom 560px)"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-circle-005-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-circle-005-expected.txt
new file mode 100644
index 0000000..ec19c464
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-circle-005-expected.txt
@@ -0,0 +1,59 @@
+This is a testharness.js-based test.
+Found 52 tests; 48 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] test unit: cm - circle(50cm at 50% 50%) - inline
+[PASS] test unit: cm - circle(50cm) - inline
+[PASS] test unit: mm - circle(50mm at 50% 50%) - inline
+[PASS] test unit: mm - circle(50mm) - inline
+[PASS] test unit: in - circle(50in at 50% 50%) - inline
+[PASS] test unit: in - circle(50in) - inline
+[PASS] test unit: pt - circle(50pt at 50% 50%) - inline
+[PASS] test unit: pt - circle(50pt) - inline
+[PASS] test unit: pc - circle(50pc at 50% 50%) - inline
+[PASS] test unit: pc - circle(50pc) - inline
+[PASS] test unit: em - circle(50em at 50% 50%) - inline
+[PASS] test unit: em - circle(50em) - inline
+[PASS] test unit: ex - circle(50ex at 50% 50%) - inline
+[PASS] test unit: ex - circle(50ex) - inline
+[PASS] test unit: ch - circle(50ch at 50% 50%) - inline
+[PASS] test unit: ch - circle(50ch) - inline
+[PASS] test unit: rem - circle(50rem at 50% 50%) - inline
+[PASS] test unit: rem - circle(50rem) - inline
+[PASS] test unit: vw - circle(50vw at 50% 50%) - inline
+[PASS] test unit: vw - circle(50vw) - inline
+[PASS] test unit: vh - circle(50vh at 50% 50%) - inline
+[PASS] test unit: vh - circle(50vh) - inline
+[PASS] test unit: vmin - circle(50vmin at 50% 50%) - inline
+[PASS] test unit: vmin - circle(50vmin) - inline
+[PASS] test unit: vmax - circle(50vmax at 50% 50%) - inline
+[PASS] test unit: vmax - circle(50vmax) - inline
+[PASS] test unit: cm - circle(50cm at 50% 50%) - computed
+[PASS] test unit: cm - circle(50cm) - computed
+[PASS] test unit: mm - circle(50mm at 50% 50%) - computed
+[PASS] test unit: mm - circle(50mm) - computed
+[PASS] test unit: in - circle(50in at 50% 50%) - computed
+[PASS] test unit: in - circle(50in) - computed
+[PASS] test unit: pt - circle(50pt at 50% 50%) - computed
+[PASS] test unit: pt - circle(50pt) - computed
+[PASS] test unit: pc - circle(50pc at 50% 50%) - computed
+[PASS] test unit: pc - circle(50pc) - computed
+[PASS] test unit: em - circle(50em at 50% 50%) - computed
+[PASS] test unit: em - circle(50em) - computed
+[FAIL] test unit: ex - circle(50ex at 50% 50%) - computed
+  assert_equals: expected "circle(640px at 50% 50%)" but got "circle(400px at 50% 50%)"
+[FAIL] test unit: ex - circle(50ex) - computed
+  assert_equals: expected "circle(640px)" but got "circle(400px)"
+[FAIL] test unit: ch - circle(50ch at 50% 50%) - computed
+  assert_equals: expected "circle(800px at 50% 50%)" but got "circle(400px at 50% 50%)"
+[FAIL] test unit: ch - circle(50ch) - computed
+  assert_equals: expected "circle(800px)" but got "circle(400px)"
+[PASS] test unit: rem - circle(50rem at 50% 50%) - computed
+[PASS] test unit: rem - circle(50rem) - computed
+[PASS] test unit: vw - circle(50vw at 50% 50%) - computed
+[PASS] test unit: vw - circle(50vw) - computed
+[PASS] test unit: vh - circle(50vh at 50% 50%) - computed
+[PASS] test unit: vh - circle(50vh) - computed
+[PASS] test unit: vmin - circle(50vmin at 50% 50%) - computed
+[PASS] test unit: vmin - circle(50vmin) - computed
+[PASS] test unit: vmax - circle(50vmax at 50% 50%) - computed
+[PASS] test unit: vmax - circle(50vmax) - computed
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-ellipse-005-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-ellipse-005-expected.txt
new file mode 100644
index 0000000..c411d1fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-ellipse-005-expected.txt
@@ -0,0 +1,451 @@
+This is a testharness.js-based test.
+Found 416 tests; 384 PASS, 32 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] test unit: cm - ellipse(50cm 100cm at 50% 50%) - inline
+[PASS] test unit: cm - ellipse(100cm 100px at 50% 50%) - inline
+[PASS] test unit: cm - ellipse(50cm 25% at 50% 50%) - inline
+[PASS] test unit: cm - ellipse(25% 50cm at 50% 50%) - inline
+[PASS] test unit: cm - ellipse(25cm closest-side at 50% 50%) - inline
+[PASS] test unit: cm - ellipse(closest-side 75cm at 50% 50%) - inline
+[PASS] test unit: cm - ellipse(25cm farthest-side at 50% 50%) - inline
+[PASS] test unit: cm - ellipse(farthest-side 75cm at 50% 50%) - inline
+[PASS] test unit: cm - ellipse(50cm 100cm) - inline
+[PASS] test unit: cm - ellipse(100cm 100px) - inline
+[PASS] test unit: cm - ellipse(50cm 25%) - inline
+[PASS] test unit: cm - ellipse(25% 50cm) - inline
+[PASS] test unit: cm - ellipse(25cm closest-side) - inline
+[PASS] test unit: cm - ellipse(closest-side 75cm) - inline
+[PASS] test unit: cm - ellipse(25cm farthest-side) - inline
+[PASS] test unit: cm - ellipse(farthest-side 75cm) - inline
+[PASS] test unit: mm - ellipse(50mm 100mm at 50% 50%) - inline
+[PASS] test unit: mm - ellipse(100mm 100px at 50% 50%) - inline
+[PASS] test unit: mm - ellipse(50mm 25% at 50% 50%) - inline
+[PASS] test unit: mm - ellipse(25% 50mm at 50% 50%) - inline
+[PASS] test unit: mm - ellipse(25mm closest-side at 50% 50%) - inline
+[PASS] test unit: mm - ellipse(closest-side 75mm at 50% 50%) - inline
+[PASS] test unit: mm - ellipse(25mm farthest-side at 50% 50%) - inline
+[PASS] test unit: mm - ellipse(farthest-side 75mm at 50% 50%) - inline
+[PASS] test unit: mm - ellipse(50mm 100mm) - inline
+[PASS] test unit: mm - ellipse(100mm 100px) - inline
+[PASS] test unit: mm - ellipse(50mm 25%) - inline
+[PASS] test unit: mm - ellipse(25% 50mm) - inline
+[PASS] test unit: mm - ellipse(25mm closest-side) - inline
+[PASS] test unit: mm - ellipse(closest-side 75mm) - inline
+[PASS] test unit: mm - ellipse(25mm farthest-side) - inline
+[PASS] test unit: mm - ellipse(farthest-side 75mm) - inline
+[PASS] test unit: in - ellipse(50in 100in at 50% 50%) - inline
+[PASS] test unit: in - ellipse(100in 100px at 50% 50%) - inline
+[PASS] test unit: in - ellipse(50in 25% at 50% 50%) - inline
+[PASS] test unit: in - ellipse(25% 50in at 50% 50%) - inline
+[PASS] test unit: in - ellipse(25in closest-side at 50% 50%) - inline
+[PASS] test unit: in - ellipse(closest-side 75in at 50% 50%) - inline
+[PASS] test unit: in - ellipse(25in farthest-side at 50% 50%) - inline
+[PASS] test unit: in - ellipse(farthest-side 75in at 50% 50%) - inline
+[PASS] test unit: in - ellipse(50in 100in) - inline
+[PASS] test unit: in - ellipse(100in 100px) - inline
+[PASS] test unit: in - ellipse(50in 25%) - inline
+[PASS] test unit: in - ellipse(25% 50in) - inline
+[PASS] test unit: in - ellipse(25in closest-side) - inline
+[PASS] test unit: in - ellipse(closest-side 75in) - inline
+[PASS] test unit: in - ellipse(25in farthest-side) - inline
+[PASS] test unit: in - ellipse(farthest-side 75in) - inline
+[PASS] test unit: pt - ellipse(50pt 100pt at 50% 50%) - inline
+[PASS] test unit: pt - ellipse(100pt 100px at 50% 50%) - inline
+[PASS] test unit: pt - ellipse(50pt 25% at 50% 50%) - inline
+[PASS] test unit: pt - ellipse(25% 50pt at 50% 50%) - inline
+[PASS] test unit: pt - ellipse(25pt closest-side at 50% 50%) - inline
+[PASS] test unit: pt - ellipse(closest-side 75pt at 50% 50%) - inline
+[PASS] test unit: pt - ellipse(25pt farthest-side at 50% 50%) - inline
+[PASS] test unit: pt - ellipse(farthest-side 75pt at 50% 50%) - inline
+[PASS] test unit: pt - ellipse(50pt 100pt) - inline
+[PASS] test unit: pt - ellipse(100pt 100px) - inline
+[PASS] test unit: pt - ellipse(50pt 25%) - inline
+[PASS] test unit: pt - ellipse(25% 50pt) - inline
+[PASS] test unit: pt - ellipse(25pt closest-side) - inline
+[PASS] test unit: pt - ellipse(closest-side 75pt) - inline
+[PASS] test unit: pt - ellipse(25pt farthest-side) - inline
+[PASS] test unit: pt - ellipse(farthest-side 75pt) - inline
+[PASS] test unit: pc - ellipse(50pc 100pc at 50% 50%) - inline
+[PASS] test unit: pc - ellipse(100pc 100px at 50% 50%) - inline
+[PASS] test unit: pc - ellipse(50pc 25% at 50% 50%) - inline
+[PASS] test unit: pc - ellipse(25% 50pc at 50% 50%) - inline
+[PASS] test unit: pc - ellipse(25pc closest-side at 50% 50%) - inline
+[PASS] test unit: pc - ellipse(closest-side 75pc at 50% 50%) - inline
+[PASS] test unit: pc - ellipse(25pc farthest-side at 50% 50%) - inline
+[PASS] test unit: pc - ellipse(farthest-side 75pc at 50% 50%) - inline
+[PASS] test unit: pc - ellipse(50pc 100pc) - inline
+[PASS] test unit: pc - ellipse(100pc 100px) - inline
+[PASS] test unit: pc - ellipse(50pc 25%) - inline
+[PASS] test unit: pc - ellipse(25% 50pc) - inline
+[PASS] test unit: pc - ellipse(25pc closest-side) - inline
+[PASS] test unit: pc - ellipse(closest-side 75pc) - inline
+[PASS] test unit: pc - ellipse(25pc farthest-side) - inline
+[PASS] test unit: pc - ellipse(farthest-side 75pc) - inline
+[PASS] test unit: em - ellipse(50em 100em at 50% 50%) - inline
+[PASS] test unit: em - ellipse(100em 100px at 50% 50%) - inline
+[PASS] test unit: em - ellipse(50em 25% at 50% 50%) - inline
+[PASS] test unit: em - ellipse(25% 50em at 50% 50%) - inline
+[PASS] test unit: em - ellipse(25em closest-side at 50% 50%) - inline
+[PASS] test unit: em - ellipse(closest-side 75em at 50% 50%) - inline
+[PASS] test unit: em - ellipse(25em farthest-side at 50% 50%) - inline
+[PASS] test unit: em - ellipse(farthest-side 75em at 50% 50%) - inline
+[PASS] test unit: em - ellipse(50em 100em) - inline
+[PASS] test unit: em - ellipse(100em 100px) - inline
+[PASS] test unit: em - ellipse(50em 25%) - inline
+[PASS] test unit: em - ellipse(25% 50em) - inline
+[PASS] test unit: em - ellipse(25em closest-side) - inline
+[PASS] test unit: em - ellipse(closest-side 75em) - inline
+[PASS] test unit: em - ellipse(25em farthest-side) - inline
+[PASS] test unit: em - ellipse(farthest-side 75em) - inline
+[PASS] test unit: ex - ellipse(50ex 100ex at 50% 50%) - inline
+[PASS] test unit: ex - ellipse(100ex 100px at 50% 50%) - inline
+[PASS] test unit: ex - ellipse(50ex 25% at 50% 50%) - inline
+[PASS] test unit: ex - ellipse(25% 50ex at 50% 50%) - inline
+[PASS] test unit: ex - ellipse(25ex closest-side at 50% 50%) - inline
+[PASS] test unit: ex - ellipse(closest-side 75ex at 50% 50%) - inline
+[PASS] test unit: ex - ellipse(25ex farthest-side at 50% 50%) - inline
+[PASS] test unit: ex - ellipse(farthest-side 75ex at 50% 50%) - inline
+[PASS] test unit: ex - ellipse(50ex 100ex) - inline
+[PASS] test unit: ex - ellipse(100ex 100px) - inline
+[PASS] test unit: ex - ellipse(50ex 25%) - inline
+[PASS] test unit: ex - ellipse(25% 50ex) - inline
+[PASS] test unit: ex - ellipse(25ex closest-side) - inline
+[PASS] test unit: ex - ellipse(closest-side 75ex) - inline
+[PASS] test unit: ex - ellipse(25ex farthest-side) - inline
+[PASS] test unit: ex - ellipse(farthest-side 75ex) - inline
+[PASS] test unit: ch - ellipse(50ch 100ch at 50% 50%) - inline
+[PASS] test unit: ch - ellipse(100ch 100px at 50% 50%) - inline
+[PASS] test unit: ch - ellipse(50ch 25% at 50% 50%) - inline
+[PASS] test unit: ch - ellipse(25% 50ch at 50% 50%) - inline
+[PASS] test unit: ch - ellipse(25ch closest-side at 50% 50%) - inline
+[PASS] test unit: ch - ellipse(closest-side 75ch at 50% 50%) - inline
+[PASS] test unit: ch - ellipse(25ch farthest-side at 50% 50%) - inline
+[PASS] test unit: ch - ellipse(farthest-side 75ch at 50% 50%) - inline
+[PASS] test unit: ch - ellipse(50ch 100ch) - inline
+[PASS] test unit: ch - ellipse(100ch 100px) - inline
+[PASS] test unit: ch - ellipse(50ch 25%) - inline
+[PASS] test unit: ch - ellipse(25% 50ch) - inline
+[PASS] test unit: ch - ellipse(25ch closest-side) - inline
+[PASS] test unit: ch - ellipse(closest-side 75ch) - inline
+[PASS] test unit: ch - ellipse(25ch farthest-side) - inline
+[PASS] test unit: ch - ellipse(farthest-side 75ch) - inline
+[PASS] test unit: rem - ellipse(50rem 100rem at 50% 50%) - inline
+[PASS] test unit: rem - ellipse(100rem 100px at 50% 50%) - inline
+[PASS] test unit: rem - ellipse(50rem 25% at 50% 50%) - inline
+[PASS] test unit: rem - ellipse(25% 50rem at 50% 50%) - inline
+[PASS] test unit: rem - ellipse(25rem closest-side at 50% 50%) - inline
+[PASS] test unit: rem - ellipse(closest-side 75rem at 50% 50%) - inline
+[PASS] test unit: rem - ellipse(25rem farthest-side at 50% 50%) - inline
+[PASS] test unit: rem - ellipse(farthest-side 75rem at 50% 50%) - inline
+[PASS] test unit: rem - ellipse(50rem 100rem) - inline
+[PASS] test unit: rem - ellipse(100rem 100px) - inline
+[PASS] test unit: rem - ellipse(50rem 25%) - inline
+[PASS] test unit: rem - ellipse(25% 50rem) - inline
+[PASS] test unit: rem - ellipse(25rem closest-side) - inline
+[PASS] test unit: rem - ellipse(closest-side 75rem) - inline
+[PASS] test unit: rem - ellipse(25rem farthest-side) - inline
+[PASS] test unit: rem - ellipse(farthest-side 75rem) - inline
+[PASS] test unit: vw - ellipse(50vw 100vw at 50% 50%) - inline
+[PASS] test unit: vw - ellipse(100vw 100px at 50% 50%) - inline
+[PASS] test unit: vw - ellipse(50vw 25% at 50% 50%) - inline
+[PASS] test unit: vw - ellipse(25% 50vw at 50% 50%) - inline
+[PASS] test unit: vw - ellipse(25vw closest-side at 50% 50%) - inline
+[PASS] test unit: vw - ellipse(closest-side 75vw at 50% 50%) - inline
+[PASS] test unit: vw - ellipse(25vw farthest-side at 50% 50%) - inline
+[PASS] test unit: vw - ellipse(farthest-side 75vw at 50% 50%) - inline
+[PASS] test unit: vw - ellipse(50vw 100vw) - inline
+[PASS] test unit: vw - ellipse(100vw 100px) - inline
+[PASS] test unit: vw - ellipse(50vw 25%) - inline
+[PASS] test unit: vw - ellipse(25% 50vw) - inline
+[PASS] test unit: vw - ellipse(25vw closest-side) - inline
+[PASS] test unit: vw - ellipse(closest-side 75vw) - inline
+[PASS] test unit: vw - ellipse(25vw farthest-side) - inline
+[PASS] test unit: vw - ellipse(farthest-side 75vw) - inline
+[PASS] test unit: vh - ellipse(50vh 100vh at 50% 50%) - inline
+[PASS] test unit: vh - ellipse(100vh 100px at 50% 50%) - inline
+[PASS] test unit: vh - ellipse(50vh 25% at 50% 50%) - inline
+[PASS] test unit: vh - ellipse(25% 50vh at 50% 50%) - inline
+[PASS] test unit: vh - ellipse(25vh closest-side at 50% 50%) - inline
+[PASS] test unit: vh - ellipse(closest-side 75vh at 50% 50%) - inline
+[PASS] test unit: vh - ellipse(25vh farthest-side at 50% 50%) - inline
+[PASS] test unit: vh - ellipse(farthest-side 75vh at 50% 50%) - inline
+[PASS] test unit: vh - ellipse(50vh 100vh) - inline
+[PASS] test unit: vh - ellipse(100vh 100px) - inline
+[PASS] test unit: vh - ellipse(50vh 25%) - inline
+[PASS] test unit: vh - ellipse(25% 50vh) - inline
+[PASS] test unit: vh - ellipse(25vh closest-side) - inline
+[PASS] test unit: vh - ellipse(closest-side 75vh) - inline
+[PASS] test unit: vh - ellipse(25vh farthest-side) - inline
+[PASS] test unit: vh - ellipse(farthest-side 75vh) - inline
+[PASS] test unit: vmin - ellipse(50vmin 100vmin at 50% 50%) - inline
+[PASS] test unit: vmin - ellipse(100vmin 100px at 50% 50%) - inline
+[PASS] test unit: vmin - ellipse(50vmin 25% at 50% 50%) - inline
+[PASS] test unit: vmin - ellipse(25% 50vmin at 50% 50%) - inline
+[PASS] test unit: vmin - ellipse(25vmin closest-side at 50% 50%) - inline
+[PASS] test unit: vmin - ellipse(closest-side 75vmin at 50% 50%) - inline
+[PASS] test unit: vmin - ellipse(25vmin farthest-side at 50% 50%) - inline
+[PASS] test unit: vmin - ellipse(farthest-side 75vmin at 50% 50%) - inline
+[PASS] test unit: vmin - ellipse(50vmin 100vmin) - inline
+[PASS] test unit: vmin - ellipse(100vmin 100px) - inline
+[PASS] test unit: vmin - ellipse(50vmin 25%) - inline
+[PASS] test unit: vmin - ellipse(25% 50vmin) - inline
+[PASS] test unit: vmin - ellipse(25vmin closest-side) - inline
+[PASS] test unit: vmin - ellipse(closest-side 75vmin) - inline
+[PASS] test unit: vmin - ellipse(25vmin farthest-side) - inline
+[PASS] test unit: vmin - ellipse(farthest-side 75vmin) - inline
+[PASS] test unit: vmax - ellipse(50vmax 100vmax at 50% 50%) - inline
+[PASS] test unit: vmax - ellipse(100vmax 100px at 50% 50%) - inline
+[PASS] test unit: vmax - ellipse(50vmax 25% at 50% 50%) - inline
+[PASS] test unit: vmax - ellipse(25% 50vmax at 50% 50%) - inline
+[PASS] test unit: vmax - ellipse(25vmax closest-side at 50% 50%) - inline
+[PASS] test unit: vmax - ellipse(closest-side 75vmax at 50% 50%) - inline
+[PASS] test unit: vmax - ellipse(25vmax farthest-side at 50% 50%) - inline
+[PASS] test unit: vmax - ellipse(farthest-side 75vmax at 50% 50%) - inline
+[PASS] test unit: vmax - ellipse(50vmax 100vmax) - inline
+[PASS] test unit: vmax - ellipse(100vmax 100px) - inline
+[PASS] test unit: vmax - ellipse(50vmax 25%) - inline
+[PASS] test unit: vmax - ellipse(25% 50vmax) - inline
+[PASS] test unit: vmax - ellipse(25vmax closest-side) - inline
+[PASS] test unit: vmax - ellipse(closest-side 75vmax) - inline
+[PASS] test unit: vmax - ellipse(25vmax farthest-side) - inline
+[PASS] test unit: vmax - ellipse(farthest-side 75vmax) - inline
+[PASS] test unit: cm - ellipse(50cm 100cm at 50% 50%) - computed
+[PASS] test unit: cm - ellipse(100cm 100px at 50% 50%) - computed
+[PASS] test unit: cm - ellipse(50cm 25% at 50% 50%) - computed
+[PASS] test unit: cm - ellipse(25% 50cm at 50% 50%) - computed
+[PASS] test unit: cm - ellipse(25cm closest-side at 50% 50%) - computed
+[PASS] test unit: cm - ellipse(closest-side 75cm at 50% 50%) - computed
+[PASS] test unit: cm - ellipse(25cm farthest-side at 50% 50%) - computed
+[PASS] test unit: cm - ellipse(farthest-side 75cm at 50% 50%) - computed
+[PASS] test unit: cm - ellipse(50cm 100cm) - computed
+[PASS] test unit: cm - ellipse(100cm 100px) - computed
+[PASS] test unit: cm - ellipse(50cm 25%) - computed
+[PASS] test unit: cm - ellipse(25% 50cm) - computed
+[PASS] test unit: cm - ellipse(25cm closest-side) - computed
+[PASS] test unit: cm - ellipse(closest-side 75cm) - computed
+[PASS] test unit: cm - ellipse(25cm farthest-side) - computed
+[PASS] test unit: cm - ellipse(farthest-side 75cm) - computed
+[PASS] test unit: mm - ellipse(50mm 100mm at 50% 50%) - computed
+[PASS] test unit: mm - ellipse(100mm 100px at 50% 50%) - computed
+[PASS] test unit: mm - ellipse(50mm 25% at 50% 50%) - computed
+[PASS] test unit: mm - ellipse(25% 50mm at 50% 50%) - computed
+[PASS] test unit: mm - ellipse(25mm closest-side at 50% 50%) - computed
+[PASS] test unit: mm - ellipse(closest-side 75mm at 50% 50%) - computed
+[PASS] test unit: mm - ellipse(25mm farthest-side at 50% 50%) - computed
+[PASS] test unit: mm - ellipse(farthest-side 75mm at 50% 50%) - computed
+[PASS] test unit: mm - ellipse(50mm 100mm) - computed
+[PASS] test unit: mm - ellipse(100mm 100px) - computed
+[PASS] test unit: mm - ellipse(50mm 25%) - computed
+[PASS] test unit: mm - ellipse(25% 50mm) - computed
+[PASS] test unit: mm - ellipse(25mm closest-side) - computed
+[PASS] test unit: mm - ellipse(closest-side 75mm) - computed
+[PASS] test unit: mm - ellipse(25mm farthest-side) - computed
+[PASS] test unit: mm - ellipse(farthest-side 75mm) - computed
+[PASS] test unit: in - ellipse(50in 100in at 50% 50%) - computed
+[PASS] test unit: in - ellipse(100in 100px at 50% 50%) - computed
+[PASS] test unit: in - ellipse(50in 25% at 50% 50%) - computed
+[PASS] test unit: in - ellipse(25% 50in at 50% 50%) - computed
+[PASS] test unit: in - ellipse(25in closest-side at 50% 50%) - computed
+[PASS] test unit: in - ellipse(closest-side 75in at 50% 50%) - computed
+[PASS] test unit: in - ellipse(25in farthest-side at 50% 50%) - computed
+[PASS] test unit: in - ellipse(farthest-side 75in at 50% 50%) - computed
+[PASS] test unit: in - ellipse(50in 100in) - computed
+[PASS] test unit: in - ellipse(100in 100px) - computed
+[PASS] test unit: in - ellipse(50in 25%) - computed
+[PASS] test unit: in - ellipse(25% 50in) - computed
+[PASS] test unit: in - ellipse(25in closest-side) - computed
+[PASS] test unit: in - ellipse(closest-side 75in) - computed
+[PASS] test unit: in - ellipse(25in farthest-side) - computed
+[PASS] test unit: in - ellipse(farthest-side 75in) - computed
+[PASS] test unit: pt - ellipse(50pt 100pt at 50% 50%) - computed
+[PASS] test unit: pt - ellipse(100pt 100px at 50% 50%) - computed
+[PASS] test unit: pt - ellipse(50pt 25% at 50% 50%) - computed
+[PASS] test unit: pt - ellipse(25% 50pt at 50% 50%) - computed
+[PASS] test unit: pt - ellipse(25pt closest-side at 50% 50%) - computed
+[PASS] test unit: pt - ellipse(closest-side 75pt at 50% 50%) - computed
+[PASS] test unit: pt - ellipse(25pt farthest-side at 50% 50%) - computed
+[PASS] test unit: pt - ellipse(farthest-side 75pt at 50% 50%) - computed
+[PASS] test unit: pt - ellipse(50pt 100pt) - computed
+[PASS] test unit: pt - ellipse(100pt 100px) - computed
+[PASS] test unit: pt - ellipse(50pt 25%) - computed
+[PASS] test unit: pt - ellipse(25% 50pt) - computed
+[PASS] test unit: pt - ellipse(25pt closest-side) - computed
+[PASS] test unit: pt - ellipse(closest-side 75pt) - computed
+[PASS] test unit: pt - ellipse(25pt farthest-side) - computed
+[PASS] test unit: pt - ellipse(farthest-side 75pt) - computed
+[PASS] test unit: pc - ellipse(50pc 100pc at 50% 50%) - computed
+[PASS] test unit: pc - ellipse(100pc 100px at 50% 50%) - computed
+[PASS] test unit: pc - ellipse(50pc 25% at 50% 50%) - computed
+[PASS] test unit: pc - ellipse(25% 50pc at 50% 50%) - computed
+[PASS] test unit: pc - ellipse(25pc closest-side at 50% 50%) - computed
+[PASS] test unit: pc - ellipse(closest-side 75pc at 50% 50%) - computed
+[PASS] test unit: pc - ellipse(25pc farthest-side at 50% 50%) - computed
+[PASS] test unit: pc - ellipse(farthest-side 75pc at 50% 50%) - computed
+[PASS] test unit: pc - ellipse(50pc 100pc) - computed
+[PASS] test unit: pc - ellipse(100pc 100px) - computed
+[PASS] test unit: pc - ellipse(50pc 25%) - computed
+[PASS] test unit: pc - ellipse(25% 50pc) - computed
+[PASS] test unit: pc - ellipse(25pc closest-side) - computed
+[PASS] test unit: pc - ellipse(closest-side 75pc) - computed
+[PASS] test unit: pc - ellipse(25pc farthest-side) - computed
+[PASS] test unit: pc - ellipse(farthest-side 75pc) - computed
+[PASS] test unit: em - ellipse(50em 100em at 50% 50%) - computed
+[PASS] test unit: em - ellipse(100em 100px at 50% 50%) - computed
+[PASS] test unit: em - ellipse(50em 25% at 50% 50%) - computed
+[PASS] test unit: em - ellipse(25% 50em at 50% 50%) - computed
+[PASS] test unit: em - ellipse(25em closest-side at 50% 50%) - computed
+[PASS] test unit: em - ellipse(closest-side 75em at 50% 50%) - computed
+[PASS] test unit: em - ellipse(25em farthest-side at 50% 50%) - computed
+[PASS] test unit: em - ellipse(farthest-side 75em at 50% 50%) - computed
+[PASS] test unit: em - ellipse(50em 100em) - computed
+[PASS] test unit: em - ellipse(100em 100px) - computed
+[PASS] test unit: em - ellipse(50em 25%) - computed
+[PASS] test unit: em - ellipse(25% 50em) - computed
+[PASS] test unit: em - ellipse(25em closest-side) - computed
+[PASS] test unit: em - ellipse(closest-side 75em) - computed
+[PASS] test unit: em - ellipse(25em farthest-side) - computed
+[PASS] test unit: em - ellipse(farthest-side 75em) - computed
+[FAIL] test unit: ex - ellipse(50ex 100ex at 50% 50%) - computed
+  assert_equals: expected "ellipse(640px 1280px at 50% 50%)" but got "ellipse(400px 800px at 50% 50%)"
+[FAIL] test unit: ex - ellipse(100ex 100px at 50% 50%) - computed
+  assert_equals: expected "ellipse(1280px 100px at 50% 50%)" but got "ellipse(800px 100px at 50% 50%)"
+[FAIL] test unit: ex - ellipse(50ex 25% at 50% 50%) - computed
+  assert_equals: expected "ellipse(640px 25% at 50% 50%)" but got "ellipse(400px 25% at 50% 50%)"
+[FAIL] test unit: ex - ellipse(25% 50ex at 50% 50%) - computed
+  assert_equals: expected "ellipse(25% 640px at 50% 50%)" but got "ellipse(25% 400px at 50% 50%)"
+[FAIL] test unit: ex - ellipse(25ex closest-side at 50% 50%) - computed
+  assert_equals: expected "ellipse(320px closest-side at 50% 50%)" but got "ellipse(200px closest-side at 50% 50%)"
+[FAIL] test unit: ex - ellipse(closest-side 75ex at 50% 50%) - computed
+  assert_equals: expected "ellipse(closest-side 960px at 50% 50%)" but got "ellipse(closest-side 600px at 50% 50%)"
+[FAIL] test unit: ex - ellipse(25ex farthest-side at 50% 50%) - computed
+  assert_equals: expected "ellipse(320px farthest-side at 50% 50%)" but got "ellipse(200px farthest-side at 50% 50%)"
+[FAIL] test unit: ex - ellipse(farthest-side 75ex at 50% 50%) - computed
+  assert_equals: expected "ellipse(farthest-side 960px at 50% 50%)" but got "ellipse(farthest-side 600px at 50% 50%)"
+[FAIL] test unit: ex - ellipse(50ex 100ex) - computed
+  assert_equals: expected "ellipse(640px 1280px)" but got "ellipse(400px 800px)"
+[FAIL] test unit: ex - ellipse(100ex 100px) - computed
+  assert_equals: expected "ellipse(1280px 100px)" but got "ellipse(800px 100px)"
+[FAIL] test unit: ex - ellipse(50ex 25%) - computed
+  assert_equals: expected "ellipse(640px 25%)" but got "ellipse(400px 25%)"
+[FAIL] test unit: ex - ellipse(25% 50ex) - computed
+  assert_equals: expected "ellipse(25% 640px)" but got "ellipse(25% 400px)"
+[FAIL] test unit: ex - ellipse(25ex closest-side) - computed
+  assert_equals: expected "ellipse(320px closest-side)" but got "ellipse(200px closest-side)"
+[FAIL] test unit: ex - ellipse(closest-side 75ex) - computed
+  assert_equals: expected "ellipse(closest-side 960px)" but got "ellipse(closest-side 600px)"
+[FAIL] test unit: ex - ellipse(25ex farthest-side) - computed
+  assert_equals: expected "ellipse(320px farthest-side)" but got "ellipse(200px farthest-side)"
+[FAIL] test unit: ex - ellipse(farthest-side 75ex) - computed
+  assert_equals: expected "ellipse(farthest-side 960px)" but got "ellipse(farthest-side 600px)"
+[FAIL] test unit: ch - ellipse(50ch 100ch at 50% 50%) - computed
+  assert_equals: expected "ellipse(800px 1600px at 50% 50%)" but got "ellipse(400px 800px at 50% 50%)"
+[FAIL] test unit: ch - ellipse(100ch 100px at 50% 50%) - computed
+  assert_equals: expected "ellipse(1600px 100px at 50% 50%)" but got "ellipse(800px 100px at 50% 50%)"
+[FAIL] test unit: ch - ellipse(50ch 25% at 50% 50%) - computed
+  assert_equals: expected "ellipse(800px 25% at 50% 50%)" but got "ellipse(400px 25% at 50% 50%)"
+[FAIL] test unit: ch - ellipse(25% 50ch at 50% 50%) - computed
+  assert_equals: expected "ellipse(25% 800px at 50% 50%)" but got "ellipse(25% 400px at 50% 50%)"
+[FAIL] test unit: ch - ellipse(25ch closest-side at 50% 50%) - computed
+  assert_equals: expected "ellipse(400px closest-side at 50% 50%)" but got "ellipse(200px closest-side at 50% 50%)"
+[FAIL] test unit: ch - ellipse(closest-side 75ch at 50% 50%) - computed
+  assert_equals: expected "ellipse(closest-side 1200px at 50% 50%)" but got "ellipse(closest-side 600px at 50% 50%)"
+[FAIL] test unit: ch - ellipse(25ch farthest-side at 50% 50%) - computed
+  assert_equals: expected "ellipse(400px farthest-side at 50% 50%)" but got "ellipse(200px farthest-side at 50% 50%)"
+[FAIL] test unit: ch - ellipse(farthest-side 75ch at 50% 50%) - computed
+  assert_equals: expected "ellipse(farthest-side 1200px at 50% 50%)" but got "ellipse(farthest-side 600px at 50% 50%)"
+[FAIL] test unit: ch - ellipse(50ch 100ch) - computed
+  assert_equals: expected "ellipse(800px 1600px)" but got "ellipse(400px 800px)"
+[FAIL] test unit: ch - ellipse(100ch 100px) - computed
+  assert_equals: expected "ellipse(1600px 100px)" but got "ellipse(800px 100px)"
+[FAIL] test unit: ch - ellipse(50ch 25%) - computed
+  assert_equals: expected "ellipse(800px 25%)" but got "ellipse(400px 25%)"
+[FAIL] test unit: ch - ellipse(25% 50ch) - computed
+  assert_equals: expected "ellipse(25% 800px)" but got "ellipse(25% 400px)"
+[FAIL] test unit: ch - ellipse(25ch closest-side) - computed
+  assert_equals: expected "ellipse(400px closest-side)" but got "ellipse(200px closest-side)"
+[FAIL] test unit: ch - ellipse(closest-side 75ch) - computed
+  assert_equals: expected "ellipse(closest-side 1200px)" but got "ellipse(closest-side 600px)"
+[FAIL] test unit: ch - ellipse(25ch farthest-side) - computed
+  assert_equals: expected "ellipse(400px farthest-side)" but got "ellipse(200px farthest-side)"
+[FAIL] test unit: ch - ellipse(farthest-side 75ch) - computed
+  assert_equals: expected "ellipse(farthest-side 1200px)" but got "ellipse(farthest-side 600px)"
+[PASS] test unit: rem - ellipse(50rem 100rem at 50% 50%) - computed
+[PASS] test unit: rem - ellipse(100rem 100px at 50% 50%) - computed
+[PASS] test unit: rem - ellipse(50rem 25% at 50% 50%) - computed
+[PASS] test unit: rem - ellipse(25% 50rem at 50% 50%) - computed
+[PASS] test unit: rem - ellipse(25rem closest-side at 50% 50%) - computed
+[PASS] test unit: rem - ellipse(closest-side 75rem at 50% 50%) - computed
+[PASS] test unit: rem - ellipse(25rem farthest-side at 50% 50%) - computed
+[PASS] test unit: rem - ellipse(farthest-side 75rem at 50% 50%) - computed
+[PASS] test unit: rem - ellipse(50rem 100rem) - computed
+[PASS] test unit: rem - ellipse(100rem 100px) - computed
+[PASS] test unit: rem - ellipse(50rem 25%) - computed
+[PASS] test unit: rem - ellipse(25% 50rem) - computed
+[PASS] test unit: rem - ellipse(25rem closest-side) - computed
+[PASS] test unit: rem - ellipse(closest-side 75rem) - computed
+[PASS] test unit: rem - ellipse(25rem farthest-side) - computed
+[PASS] test unit: rem - ellipse(farthest-side 75rem) - computed
+[PASS] test unit: vw - ellipse(50vw 100vw at 50% 50%) - computed
+[PASS] test unit: vw - ellipse(100vw 100px at 50% 50%) - computed
+[PASS] test unit: vw - ellipse(50vw 25% at 50% 50%) - computed
+[PASS] test unit: vw - ellipse(25% 50vw at 50% 50%) - computed
+[PASS] test unit: vw - ellipse(25vw closest-side at 50% 50%) - computed
+[PASS] test unit: vw - ellipse(closest-side 75vw at 50% 50%) - computed
+[PASS] test unit: vw - ellipse(25vw farthest-side at 50% 50%) - computed
+[PASS] test unit: vw - ellipse(farthest-side 75vw at 50% 50%) - computed
+[PASS] test unit: vw - ellipse(50vw 100vw) - computed
+[PASS] test unit: vw - ellipse(100vw 100px) - computed
+[PASS] test unit: vw - ellipse(50vw 25%) - computed
+[PASS] test unit: vw - ellipse(25% 50vw) - computed
+[PASS] test unit: vw - ellipse(25vw closest-side) - computed
+[PASS] test unit: vw - ellipse(closest-side 75vw) - computed
+[PASS] test unit: vw - ellipse(25vw farthest-side) - computed
+[PASS] test unit: vw - ellipse(farthest-side 75vw) - computed
+[PASS] test unit: vh - ellipse(50vh 100vh at 50% 50%) - computed
+[PASS] test unit: vh - ellipse(100vh 100px at 50% 50%) - computed
+[PASS] test unit: vh - ellipse(50vh 25% at 50% 50%) - computed
+[PASS] test unit: vh - ellipse(25% 50vh at 50% 50%) - computed
+[PASS] test unit: vh - ellipse(25vh closest-side at 50% 50%) - computed
+[PASS] test unit: vh - ellipse(closest-side 75vh at 50% 50%) - computed
+[PASS] test unit: vh - ellipse(25vh farthest-side at 50% 50%) - computed
+[PASS] test unit: vh - ellipse(farthest-side 75vh at 50% 50%) - computed
+[PASS] test unit: vh - ellipse(50vh 100vh) - computed
+[PASS] test unit: vh - ellipse(100vh 100px) - computed
+[PASS] test unit: vh - ellipse(50vh 25%) - computed
+[PASS] test unit: vh - ellipse(25% 50vh) - computed
+[PASS] test unit: vh - ellipse(25vh closest-side) - computed
+[PASS] test unit: vh - ellipse(closest-side 75vh) - computed
+[PASS] test unit: vh - ellipse(25vh farthest-side) - computed
+[PASS] test unit: vh - ellipse(farthest-side 75vh) - computed
+[PASS] test unit: vmin - ellipse(50vmin 100vmin at 50% 50%) - computed
+[PASS] test unit: vmin - ellipse(100vmin 100px at 50% 50%) - computed
+[PASS] test unit: vmin - ellipse(50vmin 25% at 50% 50%) - computed
+[PASS] test unit: vmin - ellipse(25% 50vmin at 50% 50%) - computed
+[PASS] test unit: vmin - ellipse(25vmin closest-side at 50% 50%) - computed
+[PASS] test unit: vmin - ellipse(closest-side 75vmin at 50% 50%) - computed
+[PASS] test unit: vmin - ellipse(25vmin farthest-side at 50% 50%) - computed
+[PASS] test unit: vmin - ellipse(farthest-side 75vmin at 50% 50%) - computed
+[PASS] test unit: vmin - ellipse(50vmin 100vmin) - computed
+[PASS] test unit: vmin - ellipse(100vmin 100px) - computed
+[PASS] test unit: vmin - ellipse(50vmin 25%) - computed
+[PASS] test unit: vmin - ellipse(25% 50vmin) - computed
+[PASS] test unit: vmin - ellipse(25vmin closest-side) - computed
+[PASS] test unit: vmin - ellipse(closest-side 75vmin) - computed
+[PASS] test unit: vmin - ellipse(25vmin farthest-side) - computed
+[PASS] test unit: vmin - ellipse(farthest-side 75vmin) - computed
+[PASS] test unit: vmax - ellipse(50vmax 100vmax at 50% 50%) - computed
+[PASS] test unit: vmax - ellipse(100vmax 100px at 50% 50%) - computed
+[PASS] test unit: vmax - ellipse(50vmax 25% at 50% 50%) - computed
+[PASS] test unit: vmax - ellipse(25% 50vmax at 50% 50%) - computed
+[PASS] test unit: vmax - ellipse(25vmax closest-side at 50% 50%) - computed
+[PASS] test unit: vmax - ellipse(closest-side 75vmax at 50% 50%) - computed
+[PASS] test unit: vmax - ellipse(25vmax farthest-side at 50% 50%) - computed
+[PASS] test unit: vmax - ellipse(farthest-side 75vmax at 50% 50%) - computed
+[PASS] test unit: vmax - ellipse(50vmax 100vmax) - computed
+[PASS] test unit: vmax - ellipse(100vmax 100px) - computed
+[PASS] test unit: vmax - ellipse(50vmax 25%) - computed
+[PASS] test unit: vmax - ellipse(25% 50vmax) - computed
+[PASS] test unit: vmax - ellipse(25vmax closest-side) - computed
+[PASS] test unit: vmax - ellipse(closest-side 75vmax) - computed
+[PASS] test unit: vmax - ellipse(25vmax farthest-side) - computed
+[PASS] test unit: vmax - ellipse(farthest-side 75vmax) - computed
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-inset-003-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-inset-003-expected.txt
new file mode 100644
index 0000000..38663de
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-inset-003-expected.txt
@@ -0,0 +1,563 @@
+This is a testharness.js-based test.
+Found 520 tests; 480 PASS, 40 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] inset(10cm round 10cm) - inline
+[PASS] inset(10cm round 10cm / 10cm) - inline
+[PASS] inset(10cm round 10cm / 10cm 20cm) - inline
+[PASS] inset(10cm round 10cm / 10cm 20cm 30cm) - inline
+[PASS] inset(10cm round 10cm / 10cm 20cm 30cm 40cm) - inline
+[PASS] inset(10cm round 10cm 20cm) - inline
+[PASS] inset(10cm round 10cm 20cm / 10cm) - inline
+[PASS] inset(10cm round 10cm 20cm / 10cm 20cm) - inline
+[PASS] inset(10cm round 10cm 20cm / 10cm 20cm 30cm) - inline
+[PASS] inset(10cm round 10cm 20cm / 10cm 20cm 30cm 40cm) - inline
+[PASS] inset(10cm round 10cm 20cm 30cm) - inline
+[PASS] inset(10cm round 10cm 20cm 30cm / 10cm) - inline
+[PASS] inset(10cm round 10cm 20cm 30cm / 10cm 20cm) - inline
+[PASS] inset(10cm round 10cm 20cm 30cm / 10cm 20cm 30cm) - inline
+[PASS] inset(10cm round 10cm 20cm 30cm / 10cm 20cm 30cm 40cm) - inline
+[PASS] inset(10cm round 10cm 20cm 30cm 40cm) - inline
+[PASS] inset(10cm round 10cm 20cm 30cm 40cm / 10cm) - inline
+[PASS] inset(10cm round 10cm 20cm 30cm 40cm / 10cm 20cm) - inline
+[PASS] inset(10cm round 10cm 20cm 30cm 40cm / 10cm 20cm 30cm) - inline
+[PASS] inset(10cm round 10cm 20cm 30cm 40cm / 10cm 20cm 30cm 40cm) - inline
+[PASS] inset(10mm round 10mm) - inline
+[PASS] inset(10mm round 10mm / 10mm) - inline
+[PASS] inset(10mm round 10mm / 10mm 20mm) - inline
+[PASS] inset(10mm round 10mm / 10mm 20mm 30mm) - inline
+[PASS] inset(10mm round 10mm / 10mm 20mm 30mm 40mm) - inline
+[PASS] inset(10mm round 10mm 20mm) - inline
+[PASS] inset(10mm round 10mm 20mm / 10mm) - inline
+[PASS] inset(10mm round 10mm 20mm / 10mm 20mm) - inline
+[PASS] inset(10mm round 10mm 20mm / 10mm 20mm 30mm) - inline
+[PASS] inset(10mm round 10mm 20mm / 10mm 20mm 30mm 40mm) - inline
+[PASS] inset(10mm round 10mm 20mm 30mm) - inline
+[PASS] inset(10mm round 10mm 20mm 30mm / 10mm) - inline
+[PASS] inset(10mm round 10mm 20mm 30mm / 10mm 20mm) - inline
+[PASS] inset(10mm round 10mm 20mm 30mm / 10mm 20mm 30mm) - inline
+[PASS] inset(10mm round 10mm 20mm 30mm / 10mm 20mm 30mm 40mm) - inline
+[PASS] inset(10mm round 10mm 20mm 30mm 40mm) - inline
+[PASS] inset(10mm round 10mm 20mm 30mm 40mm / 10mm) - inline
+[PASS] inset(10mm round 10mm 20mm 30mm 40mm / 10mm 20mm) - inline
+[PASS] inset(10mm round 10mm 20mm 30mm 40mm / 10mm 20mm 30mm) - inline
+[PASS] inset(10mm round 10mm 20mm 30mm 40mm / 10mm 20mm 30mm 40mm) - inline
+[PASS] inset(10in round 10in) - inline
+[PASS] inset(10in round 10in / 10in) - inline
+[PASS] inset(10in round 10in / 10in 20in) - inline
+[PASS] inset(10in round 10in / 10in 20in 30in) - inline
+[PASS] inset(10in round 10in / 10in 20in 30in 40in) - inline
+[PASS] inset(10in round 10in 20in) - inline
+[PASS] inset(10in round 10in 20in / 10in) - inline
+[PASS] inset(10in round 10in 20in / 10in 20in) - inline
+[PASS] inset(10in round 10in 20in / 10in 20in 30in) - inline
+[PASS] inset(10in round 10in 20in / 10in 20in 30in 40in) - inline
+[PASS] inset(10in round 10in 20in 30in) - inline
+[PASS] inset(10in round 10in 20in 30in / 10in) - inline
+[PASS] inset(10in round 10in 20in 30in / 10in 20in) - inline
+[PASS] inset(10in round 10in 20in 30in / 10in 20in 30in) - inline
+[PASS] inset(10in round 10in 20in 30in / 10in 20in 30in 40in) - inline
+[PASS] inset(10in round 10in 20in 30in 40in) - inline
+[PASS] inset(10in round 10in 20in 30in 40in / 10in) - inline
+[PASS] inset(10in round 10in 20in 30in 40in / 10in 20in) - inline
+[PASS] inset(10in round 10in 20in 30in 40in / 10in 20in 30in) - inline
+[PASS] inset(10in round 10in 20in 30in 40in / 10in 20in 30in 40in) - inline
+[PASS] inset(10pt round 10pt) - inline
+[PASS] inset(10pt round 10pt / 10pt) - inline
+[PASS] inset(10pt round 10pt / 10pt 20pt) - inline
+[PASS] inset(10pt round 10pt / 10pt 20pt 30pt) - inline
+[PASS] inset(10pt round 10pt / 10pt 20pt 30pt 40pt) - inline
+[PASS] inset(10pt round 10pt 20pt) - inline
+[PASS] inset(10pt round 10pt 20pt / 10pt) - inline
+[PASS] inset(10pt round 10pt 20pt / 10pt 20pt) - inline
+[PASS] inset(10pt round 10pt 20pt / 10pt 20pt 30pt) - inline
+[PASS] inset(10pt round 10pt 20pt / 10pt 20pt 30pt 40pt) - inline
+[PASS] inset(10pt round 10pt 20pt 30pt) - inline
+[PASS] inset(10pt round 10pt 20pt 30pt / 10pt) - inline
+[PASS] inset(10pt round 10pt 20pt 30pt / 10pt 20pt) - inline
+[PASS] inset(10pt round 10pt 20pt 30pt / 10pt 20pt 30pt) - inline
+[PASS] inset(10pt round 10pt 20pt 30pt / 10pt 20pt 30pt 40pt) - inline
+[PASS] inset(10pt round 10pt 20pt 30pt 40pt) - inline
+[PASS] inset(10pt round 10pt 20pt 30pt 40pt / 10pt) - inline
+[PASS] inset(10pt round 10pt 20pt 30pt 40pt / 10pt 20pt) - inline
+[PASS] inset(10pt round 10pt 20pt 30pt 40pt / 10pt 20pt 30pt) - inline
+[PASS] inset(10pt round 10pt 20pt 30pt 40pt / 10pt 20pt 30pt 40pt) - inline
+[PASS] inset(10pc round 10pc) - inline
+[PASS] inset(10pc round 10pc / 10pc) - inline
+[PASS] inset(10pc round 10pc / 10pc 20pc) - inline
+[PASS] inset(10pc round 10pc / 10pc 20pc 30pc) - inline
+[PASS] inset(10pc round 10pc / 10pc 20pc 30pc 40pc) - inline
+[PASS] inset(10pc round 10pc 20pc) - inline
+[PASS] inset(10pc round 10pc 20pc / 10pc) - inline
+[PASS] inset(10pc round 10pc 20pc / 10pc 20pc) - inline
+[PASS] inset(10pc round 10pc 20pc / 10pc 20pc 30pc) - inline
+[PASS] inset(10pc round 10pc 20pc / 10pc 20pc 30pc 40pc) - inline
+[PASS] inset(10pc round 10pc 20pc 30pc) - inline
+[PASS] inset(10pc round 10pc 20pc 30pc / 10pc) - inline
+[PASS] inset(10pc round 10pc 20pc 30pc / 10pc 20pc) - inline
+[PASS] inset(10pc round 10pc 20pc 30pc / 10pc 20pc 30pc) - inline
+[PASS] inset(10pc round 10pc 20pc 30pc / 10pc 20pc 30pc 40pc) - inline
+[PASS] inset(10pc round 10pc 20pc 30pc 40pc) - inline
+[PASS] inset(10pc round 10pc 20pc 30pc 40pc / 10pc) - inline
+[PASS] inset(10pc round 10pc 20pc 30pc 40pc / 10pc 20pc) - inline
+[PASS] inset(10pc round 10pc 20pc 30pc 40pc / 10pc 20pc 30pc) - inline
+[PASS] inset(10pc round 10pc 20pc 30pc 40pc / 10pc 20pc 30pc 40pc) - inline
+[PASS] inset(10em round 10em) - inline
+[PASS] inset(10em round 10em / 10em) - inline
+[PASS] inset(10em round 10em / 10em 20em) - inline
+[PASS] inset(10em round 10em / 10em 20em 30em) - inline
+[PASS] inset(10em round 10em / 10em 20em 30em 40em) - inline
+[PASS] inset(10em round 10em 20em) - inline
+[PASS] inset(10em round 10em 20em / 10em) - inline
+[PASS] inset(10em round 10em 20em / 10em 20em) - inline
+[PASS] inset(10em round 10em 20em / 10em 20em 30em) - inline
+[PASS] inset(10em round 10em 20em / 10em 20em 30em 40em) - inline
+[PASS] inset(10em round 10em 20em 30em) - inline
+[PASS] inset(10em round 10em 20em 30em / 10em) - inline
+[PASS] inset(10em round 10em 20em 30em / 10em 20em) - inline
+[PASS] inset(10em round 10em 20em 30em / 10em 20em 30em) - inline
+[PASS] inset(10em round 10em 20em 30em / 10em 20em 30em 40em) - inline
+[PASS] inset(10em round 10em 20em 30em 40em) - inline
+[PASS] inset(10em round 10em 20em 30em 40em / 10em) - inline
+[PASS] inset(10em round 10em 20em 30em 40em / 10em 20em) - inline
+[PASS] inset(10em round 10em 20em 30em 40em / 10em 20em 30em) - inline
+[PASS] inset(10em round 10em 20em 30em 40em / 10em 20em 30em 40em) - inline
+[PASS] inset(10ex round 10ex) - inline
+[PASS] inset(10ex round 10ex / 10ex) - inline
+[PASS] inset(10ex round 10ex / 10ex 20ex) - inline
+[PASS] inset(10ex round 10ex / 10ex 20ex 30ex) - inline
+[PASS] inset(10ex round 10ex / 10ex 20ex 30ex 40ex) - inline
+[PASS] inset(10ex round 10ex 20ex) - inline
+[PASS] inset(10ex round 10ex 20ex / 10ex) - inline
+[PASS] inset(10ex round 10ex 20ex / 10ex 20ex) - inline
+[PASS] inset(10ex round 10ex 20ex / 10ex 20ex 30ex) - inline
+[PASS] inset(10ex round 10ex 20ex / 10ex 20ex 30ex 40ex) - inline
+[PASS] inset(10ex round 10ex 20ex 30ex) - inline
+[PASS] inset(10ex round 10ex 20ex 30ex / 10ex) - inline
+[PASS] inset(10ex round 10ex 20ex 30ex / 10ex 20ex) - inline
+[PASS] inset(10ex round 10ex 20ex 30ex / 10ex 20ex 30ex) - inline
+[PASS] inset(10ex round 10ex 20ex 30ex / 10ex 20ex 30ex 40ex) - inline
+[PASS] inset(10ex round 10ex 20ex 30ex 40ex) - inline
+[PASS] inset(10ex round 10ex 20ex 30ex 40ex / 10ex) - inline
+[PASS] inset(10ex round 10ex 20ex 30ex 40ex / 10ex 20ex) - inline
+[PASS] inset(10ex round 10ex 20ex 30ex 40ex / 10ex 20ex 30ex) - inline
+[PASS] inset(10ex round 10ex 20ex 30ex 40ex / 10ex 20ex 30ex 40ex) - inline
+[PASS] inset(10ch round 10ch) - inline
+[PASS] inset(10ch round 10ch / 10ch) - inline
+[PASS] inset(10ch round 10ch / 10ch 20ch) - inline
+[PASS] inset(10ch round 10ch / 10ch 20ch 30ch) - inline
+[PASS] inset(10ch round 10ch / 10ch 20ch 30ch 40ch) - inline
+[PASS] inset(10ch round 10ch 20ch) - inline
+[PASS] inset(10ch round 10ch 20ch / 10ch) - inline
+[PASS] inset(10ch round 10ch 20ch / 10ch 20ch) - inline
+[PASS] inset(10ch round 10ch 20ch / 10ch 20ch 30ch) - inline
+[PASS] inset(10ch round 10ch 20ch / 10ch 20ch 30ch 40ch) - inline
+[PASS] inset(10ch round 10ch 20ch 30ch) - inline
+[PASS] inset(10ch round 10ch 20ch 30ch / 10ch) - inline
+[PASS] inset(10ch round 10ch 20ch 30ch / 10ch 20ch) - inline
+[PASS] inset(10ch round 10ch 20ch 30ch / 10ch 20ch 30ch) - inline
+[PASS] inset(10ch round 10ch 20ch 30ch / 10ch 20ch 30ch 40ch) - inline
+[PASS] inset(10ch round 10ch 20ch 30ch 40ch) - inline
+[PASS] inset(10ch round 10ch 20ch 30ch 40ch / 10ch) - inline
+[PASS] inset(10ch round 10ch 20ch 30ch 40ch / 10ch 20ch) - inline
+[PASS] inset(10ch round 10ch 20ch 30ch 40ch / 10ch 20ch 30ch) - inline
+[PASS] inset(10ch round 10ch 20ch 30ch 40ch / 10ch 20ch 30ch 40ch) - inline
+[PASS] inset(10rem round 10rem) - inline
+[PASS] inset(10rem round 10rem / 10rem) - inline
+[PASS] inset(10rem round 10rem / 10rem 20rem) - inline
+[PASS] inset(10rem round 10rem / 10rem 20rem 30rem) - inline
+[PASS] inset(10rem round 10rem / 10rem 20rem 30rem 40rem) - inline
+[PASS] inset(10rem round 10rem 20rem) - inline
+[PASS] inset(10rem round 10rem 20rem / 10rem) - inline
+[PASS] inset(10rem round 10rem 20rem / 10rem 20rem) - inline
+[PASS] inset(10rem round 10rem 20rem / 10rem 20rem 30rem) - inline
+[PASS] inset(10rem round 10rem 20rem / 10rem 20rem 30rem 40rem) - inline
+[PASS] inset(10rem round 10rem 20rem 30rem) - inline
+[PASS] inset(10rem round 10rem 20rem 30rem / 10rem) - inline
+[PASS] inset(10rem round 10rem 20rem 30rem / 10rem 20rem) - inline
+[PASS] inset(10rem round 10rem 20rem 30rem / 10rem 20rem 30rem) - inline
+[PASS] inset(10rem round 10rem 20rem 30rem / 10rem 20rem 30rem 40rem) - inline
+[PASS] inset(10rem round 10rem 20rem 30rem 40rem) - inline
+[PASS] inset(10rem round 10rem 20rem 30rem 40rem / 10rem) - inline
+[PASS] inset(10rem round 10rem 20rem 30rem 40rem / 10rem 20rem) - inline
+[PASS] inset(10rem round 10rem 20rem 30rem 40rem / 10rem 20rem 30rem) - inline
+[PASS] inset(10rem round 10rem 20rem 30rem 40rem / 10rem 20rem 30rem 40rem) - inline
+[PASS] inset(10vw round 10vw) - inline
+[PASS] inset(10vw round 10vw / 10vw) - inline
+[PASS] inset(10vw round 10vw / 10vw 20vw) - inline
+[PASS] inset(10vw round 10vw / 10vw 20vw 30vw) - inline
+[PASS] inset(10vw round 10vw / 10vw 20vw 30vw 40vw) - inline
+[PASS] inset(10vw round 10vw 20vw) - inline
+[PASS] inset(10vw round 10vw 20vw / 10vw) - inline
+[PASS] inset(10vw round 10vw 20vw / 10vw 20vw) - inline
+[PASS] inset(10vw round 10vw 20vw / 10vw 20vw 30vw) - inline
+[PASS] inset(10vw round 10vw 20vw / 10vw 20vw 30vw 40vw) - inline
+[PASS] inset(10vw round 10vw 20vw 30vw) - inline
+[PASS] inset(10vw round 10vw 20vw 30vw / 10vw) - inline
+[PASS] inset(10vw round 10vw 20vw 30vw / 10vw 20vw) - inline
+[PASS] inset(10vw round 10vw 20vw 30vw / 10vw 20vw 30vw) - inline
+[PASS] inset(10vw round 10vw 20vw 30vw / 10vw 20vw 30vw 40vw) - inline
+[PASS] inset(10vw round 10vw 20vw 30vw 40vw) - inline
+[PASS] inset(10vw round 10vw 20vw 30vw 40vw / 10vw) - inline
+[PASS] inset(10vw round 10vw 20vw 30vw 40vw / 10vw 20vw) - inline
+[PASS] inset(10vw round 10vw 20vw 30vw 40vw / 10vw 20vw 30vw) - inline
+[PASS] inset(10vw round 10vw 20vw 30vw 40vw / 10vw 20vw 30vw 40vw) - inline
+[PASS] inset(10vh round 10vh) - inline
+[PASS] inset(10vh round 10vh / 10vh) - inline
+[PASS] inset(10vh round 10vh / 10vh 20vh) - inline
+[PASS] inset(10vh round 10vh / 10vh 20vh 30vh) - inline
+[PASS] inset(10vh round 10vh / 10vh 20vh 30vh 40vh) - inline
+[PASS] inset(10vh round 10vh 20vh) - inline
+[PASS] inset(10vh round 10vh 20vh / 10vh) - inline
+[PASS] inset(10vh round 10vh 20vh / 10vh 20vh) - inline
+[PASS] inset(10vh round 10vh 20vh / 10vh 20vh 30vh) - inline
+[PASS] inset(10vh round 10vh 20vh / 10vh 20vh 30vh 40vh) - inline
+[PASS] inset(10vh round 10vh 20vh 30vh) - inline
+[PASS] inset(10vh round 10vh 20vh 30vh / 10vh) - inline
+[PASS] inset(10vh round 10vh 20vh 30vh / 10vh 20vh) - inline
+[PASS] inset(10vh round 10vh 20vh 30vh / 10vh 20vh 30vh) - inline
+[PASS] inset(10vh round 10vh 20vh 30vh / 10vh 20vh 30vh 40vh) - inline
+[PASS] inset(10vh round 10vh 20vh 30vh 40vh) - inline
+[PASS] inset(10vh round 10vh 20vh 30vh 40vh / 10vh) - inline
+[PASS] inset(10vh round 10vh 20vh 30vh 40vh / 10vh 20vh) - inline
+[PASS] inset(10vh round 10vh 20vh 30vh 40vh / 10vh 20vh 30vh) - inline
+[PASS] inset(10vh round 10vh 20vh 30vh 40vh / 10vh 20vh 30vh 40vh) - inline
+[PASS] inset(10vmin round 10vmin) - inline
+[PASS] inset(10vmin round 10vmin / 10vmin) - inline
+[PASS] inset(10vmin round 10vmin / 10vmin 20vmin) - inline
+[PASS] inset(10vmin round 10vmin / 10vmin 20vmin 30vmin) - inline
+[PASS] inset(10vmin round 10vmin / 10vmin 20vmin 30vmin 40vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin / 10vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin / 10vmin 20vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin / 10vmin 20vmin 30vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin / 10vmin 20vmin 30vmin 40vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin / 10vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin / 10vmin 20vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin / 10vmin 20vmin 30vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin / 10vmin 20vmin 30vmin 40vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin 40vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin 40vmin / 10vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin 40vmin / 10vmin 20vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin 40vmin / 10vmin 20vmin 30vmin) - inline
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin 40vmin / 10vmin 20vmin 30vmin 40vmin) - inline
+[PASS] inset(10vmax round 10vmax) - inline
+[PASS] inset(10vmax round 10vmax / 10vmax) - inline
+[PASS] inset(10vmax round 10vmax / 10vmax 20vmax) - inline
+[PASS] inset(10vmax round 10vmax / 10vmax 20vmax 30vmax) - inline
+[PASS] inset(10vmax round 10vmax / 10vmax 20vmax 30vmax 40vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax / 10vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax / 10vmax 20vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax / 10vmax 20vmax 30vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax / 10vmax 20vmax 30vmax 40vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax / 10vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax / 10vmax 20vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax / 10vmax 20vmax 30vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax / 10vmax 20vmax 30vmax 40vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax 40vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax 40vmax / 10vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax 40vmax / 10vmax 20vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax 40vmax / 10vmax 20vmax 30vmax) - inline
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax 40vmax / 10vmax 20vmax 30vmax 40vmax) - inline
+[PASS] inset(10cm round 10cm) - computed
+[PASS] inset(10cm round 10cm / 10cm) - computed
+[PASS] inset(10cm round 10cm / 10cm 20cm) - computed
+[PASS] inset(10cm round 10cm / 10cm 20cm 30cm) - computed
+[PASS] inset(10cm round 10cm / 10cm 20cm 30cm 40cm) - computed
+[PASS] inset(10cm round 10cm 20cm) - computed
+[PASS] inset(10cm round 10cm 20cm / 10cm) - computed
+[PASS] inset(10cm round 10cm 20cm / 10cm 20cm) - computed
+[PASS] inset(10cm round 10cm 20cm / 10cm 20cm 30cm) - computed
+[PASS] inset(10cm round 10cm 20cm / 10cm 20cm 30cm 40cm) - computed
+[PASS] inset(10cm round 10cm 20cm 30cm) - computed
+[PASS] inset(10cm round 10cm 20cm 30cm / 10cm) - computed
+[PASS] inset(10cm round 10cm 20cm 30cm / 10cm 20cm) - computed
+[PASS] inset(10cm round 10cm 20cm 30cm / 10cm 20cm 30cm) - computed
+[PASS] inset(10cm round 10cm 20cm 30cm / 10cm 20cm 30cm 40cm) - computed
+[PASS] inset(10cm round 10cm 20cm 30cm 40cm) - computed
+[PASS] inset(10cm round 10cm 20cm 30cm 40cm / 10cm) - computed
+[PASS] inset(10cm round 10cm 20cm 30cm 40cm / 10cm 20cm) - computed
+[PASS] inset(10cm round 10cm 20cm 30cm 40cm / 10cm 20cm 30cm) - computed
+[PASS] inset(10cm round 10cm 20cm 30cm 40cm / 10cm 20cm 30cm 40cm) - computed
+[PASS] inset(10mm round 10mm) - computed
+[PASS] inset(10mm round 10mm / 10mm) - computed
+[PASS] inset(10mm round 10mm / 10mm 20mm) - computed
+[PASS] inset(10mm round 10mm / 10mm 20mm 30mm) - computed
+[PASS] inset(10mm round 10mm / 10mm 20mm 30mm 40mm) - computed
+[PASS] inset(10mm round 10mm 20mm) - computed
+[PASS] inset(10mm round 10mm 20mm / 10mm) - computed
+[PASS] inset(10mm round 10mm 20mm / 10mm 20mm) - computed
+[PASS] inset(10mm round 10mm 20mm / 10mm 20mm 30mm) - computed
+[PASS] inset(10mm round 10mm 20mm / 10mm 20mm 30mm 40mm) - computed
+[PASS] inset(10mm round 10mm 20mm 30mm) - computed
+[PASS] inset(10mm round 10mm 20mm 30mm / 10mm) - computed
+[PASS] inset(10mm round 10mm 20mm 30mm / 10mm 20mm) - computed
+[PASS] inset(10mm round 10mm 20mm 30mm / 10mm 20mm 30mm) - computed
+[PASS] inset(10mm round 10mm 20mm 30mm / 10mm 20mm 30mm 40mm) - computed
+[PASS] inset(10mm round 10mm 20mm 30mm 40mm) - computed
+[PASS] inset(10mm round 10mm 20mm 30mm 40mm / 10mm) - computed
+[PASS] inset(10mm round 10mm 20mm 30mm 40mm / 10mm 20mm) - computed
+[PASS] inset(10mm round 10mm 20mm 30mm 40mm / 10mm 20mm 30mm) - computed
+[PASS] inset(10mm round 10mm 20mm 30mm 40mm / 10mm 20mm 30mm 40mm) - computed
+[PASS] inset(10in round 10in) - computed
+[PASS] inset(10in round 10in / 10in) - computed
+[PASS] inset(10in round 10in / 10in 20in) - computed
+[PASS] inset(10in round 10in / 10in 20in 30in) - computed
+[PASS] inset(10in round 10in / 10in 20in 30in 40in) - computed
+[PASS] inset(10in round 10in 20in) - computed
+[PASS] inset(10in round 10in 20in / 10in) - computed
+[PASS] inset(10in round 10in 20in / 10in 20in) - computed
+[PASS] inset(10in round 10in 20in / 10in 20in 30in) - computed
+[PASS] inset(10in round 10in 20in / 10in 20in 30in 40in) - computed
+[PASS] inset(10in round 10in 20in 30in) - computed
+[PASS] inset(10in round 10in 20in 30in / 10in) - computed
+[PASS] inset(10in round 10in 20in 30in / 10in 20in) - computed
+[PASS] inset(10in round 10in 20in 30in / 10in 20in 30in) - computed
+[PASS] inset(10in round 10in 20in 30in / 10in 20in 30in 40in) - computed
+[PASS] inset(10in round 10in 20in 30in 40in) - computed
+[PASS] inset(10in round 10in 20in 30in 40in / 10in) - computed
+[PASS] inset(10in round 10in 20in 30in 40in / 10in 20in) - computed
+[PASS] inset(10in round 10in 20in 30in 40in / 10in 20in 30in) - computed
+[PASS] inset(10in round 10in 20in 30in 40in / 10in 20in 30in 40in) - computed
+[PASS] inset(10pt round 10pt) - computed
+[PASS] inset(10pt round 10pt / 10pt) - computed
+[PASS] inset(10pt round 10pt / 10pt 20pt) - computed
+[PASS] inset(10pt round 10pt / 10pt 20pt 30pt) - computed
+[PASS] inset(10pt round 10pt / 10pt 20pt 30pt 40pt) - computed
+[PASS] inset(10pt round 10pt 20pt) - computed
+[PASS] inset(10pt round 10pt 20pt / 10pt) - computed
+[PASS] inset(10pt round 10pt 20pt / 10pt 20pt) - computed
+[PASS] inset(10pt round 10pt 20pt / 10pt 20pt 30pt) - computed
+[PASS] inset(10pt round 10pt 20pt / 10pt 20pt 30pt 40pt) - computed
+[PASS] inset(10pt round 10pt 20pt 30pt) - computed
+[PASS] inset(10pt round 10pt 20pt 30pt / 10pt) - computed
+[PASS] inset(10pt round 10pt 20pt 30pt / 10pt 20pt) - computed
+[PASS] inset(10pt round 10pt 20pt 30pt / 10pt 20pt 30pt) - computed
+[PASS] inset(10pt round 10pt 20pt 30pt / 10pt 20pt 30pt 40pt) - computed
+[PASS] inset(10pt round 10pt 20pt 30pt 40pt) - computed
+[PASS] inset(10pt round 10pt 20pt 30pt 40pt / 10pt) - computed
+[PASS] inset(10pt round 10pt 20pt 30pt 40pt / 10pt 20pt) - computed
+[PASS] inset(10pt round 10pt 20pt 30pt 40pt / 10pt 20pt 30pt) - computed
+[PASS] inset(10pt round 10pt 20pt 30pt 40pt / 10pt 20pt 30pt 40pt) - computed
+[PASS] inset(10pc round 10pc) - computed
+[PASS] inset(10pc round 10pc / 10pc) - computed
+[PASS] inset(10pc round 10pc / 10pc 20pc) - computed
+[PASS] inset(10pc round 10pc / 10pc 20pc 30pc) - computed
+[PASS] inset(10pc round 10pc / 10pc 20pc 30pc 40pc) - computed
+[PASS] inset(10pc round 10pc 20pc) - computed
+[PASS] inset(10pc round 10pc 20pc / 10pc) - computed
+[PASS] inset(10pc round 10pc 20pc / 10pc 20pc) - computed
+[PASS] inset(10pc round 10pc 20pc / 10pc 20pc 30pc) - computed
+[PASS] inset(10pc round 10pc 20pc / 10pc 20pc 30pc 40pc) - computed
+[PASS] inset(10pc round 10pc 20pc 30pc) - computed
+[PASS] inset(10pc round 10pc 20pc 30pc / 10pc) - computed
+[PASS] inset(10pc round 10pc 20pc 30pc / 10pc 20pc) - computed
+[PASS] inset(10pc round 10pc 20pc 30pc / 10pc 20pc 30pc) - computed
+[PASS] inset(10pc round 10pc 20pc 30pc / 10pc 20pc 30pc 40pc) - computed
+[PASS] inset(10pc round 10pc 20pc 30pc 40pc) - computed
+[PASS] inset(10pc round 10pc 20pc 30pc 40pc / 10pc) - computed
+[PASS] inset(10pc round 10pc 20pc 30pc 40pc / 10pc 20pc) - computed
+[PASS] inset(10pc round 10pc 20pc 30pc 40pc / 10pc 20pc 30pc) - computed
+[PASS] inset(10pc round 10pc 20pc 30pc 40pc / 10pc 20pc 30pc 40pc) - computed
+[PASS] inset(10em round 10em) - computed
+[PASS] inset(10em round 10em / 10em) - computed
+[PASS] inset(10em round 10em / 10em 20em) - computed
+[PASS] inset(10em round 10em / 10em 20em 30em) - computed
+[PASS] inset(10em round 10em / 10em 20em 30em 40em) - computed
+[PASS] inset(10em round 10em 20em) - computed
+[PASS] inset(10em round 10em 20em / 10em) - computed
+[PASS] inset(10em round 10em 20em / 10em 20em) - computed
+[PASS] inset(10em round 10em 20em / 10em 20em 30em) - computed
+[PASS] inset(10em round 10em 20em / 10em 20em 30em 40em) - computed
+[PASS] inset(10em round 10em 20em 30em) - computed
+[PASS] inset(10em round 10em 20em 30em / 10em) - computed
+[PASS] inset(10em round 10em 20em 30em / 10em 20em) - computed
+[PASS] inset(10em round 10em 20em 30em / 10em 20em 30em) - computed
+[PASS] inset(10em round 10em 20em 30em / 10em 20em 30em 40em) - computed
+[PASS] inset(10em round 10em 20em 30em 40em) - computed
+[PASS] inset(10em round 10em 20em 30em 40em / 10em) - computed
+[PASS] inset(10em round 10em 20em 30em 40em / 10em 20em) - computed
+[PASS] inset(10em round 10em 20em 30em 40em / 10em 20em 30em) - computed
+[PASS] inset(10em round 10em 20em 30em 40em / 10em 20em 30em 40em) - computed
+[FAIL] inset(10ex round 10ex) - computed
+  assert_equals: expected "inset(128px round 128px)" but got "inset(80px round 80px)"
+[FAIL] inset(10ex round 10ex / 10ex) - computed
+  assert_equals: expected "inset(128px round 128px)" but got "inset(80px round 80px)"
+[FAIL] inset(10ex round 10ex / 10ex 20ex) - computed
+  assert_equals: expected "inset(128px round 128px / 128px 256px)" but got "inset(80px round 80px / 80px 160px)"
+[FAIL] inset(10ex round 10ex / 10ex 20ex 30ex) - computed
+  assert_equals: expected "inset(128px round 128px / 128px 256px 384px)" but got "inset(80px round 80px / 80px 160px 240px)"
+[FAIL] inset(10ex round 10ex / 10ex 20ex 30ex 40ex) - computed
+  assert_equals: expected "inset(128px round 128px / 128px 256px 384px 512px)" but got "inset(80px round 80px / 80px 160px 240px 320px)"
+[FAIL] inset(10ex round 10ex 20ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px)" but got "inset(80px round 80px 160px)"
+[FAIL] inset(10ex round 10ex 20ex / 10ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px / 128px)" but got "inset(80px round 80px 160px / 80px)"
+[FAIL] inset(10ex round 10ex 20ex / 10ex 20ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px)" but got "inset(80px round 80px 160px)"
+[FAIL] inset(10ex round 10ex 20ex / 10ex 20ex 30ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px / 128px 256px 384px)" but got "inset(80px round 80px 160px / 80px 160px 240px)"
+[FAIL] inset(10ex round 10ex 20ex / 10ex 20ex 30ex 40ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px / 128px 256px 384px 512px)" but got "inset(80px round 80px 160px / 80px 160px 240px 320px)"
+[FAIL] inset(10ex round 10ex 20ex 30ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px 384px)" but got "inset(80px round 80px 160px 240px)"
+[FAIL] inset(10ex round 10ex 20ex 30ex / 10ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px 384px / 128px)" but got "inset(80px round 80px 160px 240px / 80px)"
+[FAIL] inset(10ex round 10ex 20ex 30ex / 10ex 20ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px 384px / 128px 256px)" but got "inset(80px round 80px 160px 240px / 80px 160px)"
+[FAIL] inset(10ex round 10ex 20ex 30ex / 10ex 20ex 30ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px 384px)" but got "inset(80px round 80px 160px 240px)"
+[FAIL] inset(10ex round 10ex 20ex 30ex / 10ex 20ex 30ex 40ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px 384px / 128px 256px 384px 512px)" but got "inset(80px round 80px 160px 240px / 80px 160px 240px 320px)"
+[FAIL] inset(10ex round 10ex 20ex 30ex 40ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px 384px 512px)" but got "inset(80px round 80px 160px 240px 320px)"
+[FAIL] inset(10ex round 10ex 20ex 30ex 40ex / 10ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px 384px 512px / 128px)" but got "inset(80px round 80px 160px 240px 320px / 80px)"
+[FAIL] inset(10ex round 10ex 20ex 30ex 40ex / 10ex 20ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px 384px 512px / 128px 256px)" but got "inset(80px round 80px 160px 240px 320px / 80px 160px)"
+[FAIL] inset(10ex round 10ex 20ex 30ex 40ex / 10ex 20ex 30ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px 384px 512px / 128px 256px 384px)" but got "inset(80px round 80px 160px 240px 320px / 80px 160px 240px)"
+[FAIL] inset(10ex round 10ex 20ex 30ex 40ex / 10ex 20ex 30ex 40ex) - computed
+  assert_equals: expected "inset(128px round 128px 256px 384px 512px)" but got "inset(80px round 80px 160px 240px 320px)"
+[FAIL] inset(10ch round 10ch) - computed
+  assert_equals: expected "inset(160px round 160px)" but got "inset(80px round 80px)"
+[FAIL] inset(10ch round 10ch / 10ch) - computed
+  assert_equals: expected "inset(160px round 160px)" but got "inset(80px round 80px)"
+[FAIL] inset(10ch round 10ch / 10ch 20ch) - computed
+  assert_equals: expected "inset(160px round 160px / 160px 320px)" but got "inset(80px round 80px / 80px 160px)"
+[FAIL] inset(10ch round 10ch / 10ch 20ch 30ch) - computed
+  assert_equals: expected "inset(160px round 160px / 160px 320px 480px)" but got "inset(80px round 80px / 80px 160px 240px)"
+[FAIL] inset(10ch round 10ch / 10ch 20ch 30ch 40ch) - computed
+  assert_equals: expected "inset(160px round 160px / 160px 320px 480px 640px)" but got "inset(80px round 80px / 80px 160px 240px 320px)"
+[FAIL] inset(10ch round 10ch 20ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px)" but got "inset(80px round 80px 160px)"
+[FAIL] inset(10ch round 10ch 20ch / 10ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px / 160px)" but got "inset(80px round 80px 160px / 80px)"
+[FAIL] inset(10ch round 10ch 20ch / 10ch 20ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px)" but got "inset(80px round 80px 160px)"
+[FAIL] inset(10ch round 10ch 20ch / 10ch 20ch 30ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px / 160px 320px 480px)" but got "inset(80px round 80px 160px / 80px 160px 240px)"
+[FAIL] inset(10ch round 10ch 20ch / 10ch 20ch 30ch 40ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px / 160px 320px 480px 640px)" but got "inset(80px round 80px 160px / 80px 160px 240px 320px)"
+[FAIL] inset(10ch round 10ch 20ch 30ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px 480px)" but got "inset(80px round 80px 160px 240px)"
+[FAIL] inset(10ch round 10ch 20ch 30ch / 10ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px 480px / 160px)" but got "inset(80px round 80px 160px 240px / 80px)"
+[FAIL] inset(10ch round 10ch 20ch 30ch / 10ch 20ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px 480px / 160px 320px)" but got "inset(80px round 80px 160px 240px / 80px 160px)"
+[FAIL] inset(10ch round 10ch 20ch 30ch / 10ch 20ch 30ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px 480px)" but got "inset(80px round 80px 160px 240px)"
+[FAIL] inset(10ch round 10ch 20ch 30ch / 10ch 20ch 30ch 40ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px 480px / 160px 320px 480px 640px)" but got "inset(80px round 80px 160px 240px / 80px 160px 240px 320px)"
+[FAIL] inset(10ch round 10ch 20ch 30ch 40ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px 480px 640px)" but got "inset(80px round 80px 160px 240px 320px)"
+[FAIL] inset(10ch round 10ch 20ch 30ch 40ch / 10ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px 480px 640px / 160px)" but got "inset(80px round 80px 160px 240px 320px / 80px)"
+[FAIL] inset(10ch round 10ch 20ch 30ch 40ch / 10ch 20ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px 480px 640px / 160px 320px)" but got "inset(80px round 80px 160px 240px 320px / 80px 160px)"
+[FAIL] inset(10ch round 10ch 20ch 30ch 40ch / 10ch 20ch 30ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px 480px 640px / 160px 320px 480px)" but got "inset(80px round 80px 160px 240px 320px / 80px 160px 240px)"
+[FAIL] inset(10ch round 10ch 20ch 30ch 40ch / 10ch 20ch 30ch 40ch) - computed
+  assert_equals: expected "inset(160px round 160px 320px 480px 640px)" but got "inset(80px round 80px 160px 240px 320px)"
+[PASS] inset(10rem round 10rem) - computed
+[PASS] inset(10rem round 10rem / 10rem) - computed
+[PASS] inset(10rem round 10rem / 10rem 20rem) - computed
+[PASS] inset(10rem round 10rem / 10rem 20rem 30rem) - computed
+[PASS] inset(10rem round 10rem / 10rem 20rem 30rem 40rem) - computed
+[PASS] inset(10rem round 10rem 20rem) - computed
+[PASS] inset(10rem round 10rem 20rem / 10rem) - computed
+[PASS] inset(10rem round 10rem 20rem / 10rem 20rem) - computed
+[PASS] inset(10rem round 10rem 20rem / 10rem 20rem 30rem) - computed
+[PASS] inset(10rem round 10rem 20rem / 10rem 20rem 30rem 40rem) - computed
+[PASS] inset(10rem round 10rem 20rem 30rem) - computed
+[PASS] inset(10rem round 10rem 20rem 30rem / 10rem) - computed
+[PASS] inset(10rem round 10rem 20rem 30rem / 10rem 20rem) - computed
+[PASS] inset(10rem round 10rem 20rem 30rem / 10rem 20rem 30rem) - computed
+[PASS] inset(10rem round 10rem 20rem 30rem / 10rem 20rem 30rem 40rem) - computed
+[PASS] inset(10rem round 10rem 20rem 30rem 40rem) - computed
+[PASS] inset(10rem round 10rem 20rem 30rem 40rem / 10rem) - computed
+[PASS] inset(10rem round 10rem 20rem 30rem 40rem / 10rem 20rem) - computed
+[PASS] inset(10rem round 10rem 20rem 30rem 40rem / 10rem 20rem 30rem) - computed
+[PASS] inset(10rem round 10rem 20rem 30rem 40rem / 10rem 20rem 30rem 40rem) - computed
+[PASS] inset(10vw round 10vw) - computed
+[PASS] inset(10vw round 10vw / 10vw) - computed
+[PASS] inset(10vw round 10vw / 10vw 20vw) - computed
+[PASS] inset(10vw round 10vw / 10vw 20vw 30vw) - computed
+[PASS] inset(10vw round 10vw / 10vw 20vw 30vw 40vw) - computed
+[PASS] inset(10vw round 10vw 20vw) - computed
+[PASS] inset(10vw round 10vw 20vw / 10vw) - computed
+[PASS] inset(10vw round 10vw 20vw / 10vw 20vw) - computed
+[PASS] inset(10vw round 10vw 20vw / 10vw 20vw 30vw) - computed
+[PASS] inset(10vw round 10vw 20vw / 10vw 20vw 30vw 40vw) - computed
+[PASS] inset(10vw round 10vw 20vw 30vw) - computed
+[PASS] inset(10vw round 10vw 20vw 30vw / 10vw) - computed
+[PASS] inset(10vw round 10vw 20vw 30vw / 10vw 20vw) - computed
+[PASS] inset(10vw round 10vw 20vw 30vw / 10vw 20vw 30vw) - computed
+[PASS] inset(10vw round 10vw 20vw 30vw / 10vw 20vw 30vw 40vw) - computed
+[PASS] inset(10vw round 10vw 20vw 30vw 40vw) - computed
+[PASS] inset(10vw round 10vw 20vw 30vw 40vw / 10vw) - computed
+[PASS] inset(10vw round 10vw 20vw 30vw 40vw / 10vw 20vw) - computed
+[PASS] inset(10vw round 10vw 20vw 30vw 40vw / 10vw 20vw 30vw) - computed
+[PASS] inset(10vw round 10vw 20vw 30vw 40vw / 10vw 20vw 30vw 40vw) - computed
+[PASS] inset(10vh round 10vh) - computed
+[PASS] inset(10vh round 10vh / 10vh) - computed
+[PASS] inset(10vh round 10vh / 10vh 20vh) - computed
+[PASS] inset(10vh round 10vh / 10vh 20vh 30vh) - computed
+[PASS] inset(10vh round 10vh / 10vh 20vh 30vh 40vh) - computed
+[PASS] inset(10vh round 10vh 20vh) - computed
+[PASS] inset(10vh round 10vh 20vh / 10vh) - computed
+[PASS] inset(10vh round 10vh 20vh / 10vh 20vh) - computed
+[PASS] inset(10vh round 10vh 20vh / 10vh 20vh 30vh) - computed
+[PASS] inset(10vh round 10vh 20vh / 10vh 20vh 30vh 40vh) - computed
+[PASS] inset(10vh round 10vh 20vh 30vh) - computed
+[PASS] inset(10vh round 10vh 20vh 30vh / 10vh) - computed
+[PASS] inset(10vh round 10vh 20vh 30vh / 10vh 20vh) - computed
+[PASS] inset(10vh round 10vh 20vh 30vh / 10vh 20vh 30vh) - computed
+[PASS] inset(10vh round 10vh 20vh 30vh / 10vh 20vh 30vh 40vh) - computed
+[PASS] inset(10vh round 10vh 20vh 30vh 40vh) - computed
+[PASS] inset(10vh round 10vh 20vh 30vh 40vh / 10vh) - computed
+[PASS] inset(10vh round 10vh 20vh 30vh 40vh / 10vh 20vh) - computed
+[PASS] inset(10vh round 10vh 20vh 30vh 40vh / 10vh 20vh 30vh) - computed
+[PASS] inset(10vh round 10vh 20vh 30vh 40vh / 10vh 20vh 30vh 40vh) - computed
+[PASS] inset(10vmin round 10vmin) - computed
+[PASS] inset(10vmin round 10vmin / 10vmin) - computed
+[PASS] inset(10vmin round 10vmin / 10vmin 20vmin) - computed
+[PASS] inset(10vmin round 10vmin / 10vmin 20vmin 30vmin) - computed
+[PASS] inset(10vmin round 10vmin / 10vmin 20vmin 30vmin 40vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin / 10vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin / 10vmin 20vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin / 10vmin 20vmin 30vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin / 10vmin 20vmin 30vmin 40vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin / 10vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin / 10vmin 20vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin / 10vmin 20vmin 30vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin / 10vmin 20vmin 30vmin 40vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin 40vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin 40vmin / 10vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin 40vmin / 10vmin 20vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin 40vmin / 10vmin 20vmin 30vmin) - computed
+[PASS] inset(10vmin round 10vmin 20vmin 30vmin 40vmin / 10vmin 20vmin 30vmin 40vmin) - computed
+[PASS] inset(10vmax round 10vmax) - computed
+[PASS] inset(10vmax round 10vmax / 10vmax) - computed
+[PASS] inset(10vmax round 10vmax / 10vmax 20vmax) - computed
+[PASS] inset(10vmax round 10vmax / 10vmax 20vmax 30vmax) - computed
+[PASS] inset(10vmax round 10vmax / 10vmax 20vmax 30vmax 40vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax / 10vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax / 10vmax 20vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax / 10vmax 20vmax 30vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax / 10vmax 20vmax 30vmax 40vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax / 10vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax / 10vmax 20vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax / 10vmax 20vmax 30vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax / 10vmax 20vmax 30vmax 40vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax 40vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax 40vmax / 10vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax 40vmax / 10vmax 20vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax 40vmax / 10vmax 20vmax 30vmax) - computed
+[PASS] inset(10vmax round 10vmax 20vmax 30vmax 40vmax / 10vmax 20vmax 30vmax 40vmax) - computed
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-shape-arguments-000-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-shape-arguments-000-expected.txt
new file mode 100644
index 0000000..ba612ea
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-shapes/shape-outside/values/shape-outside-shape-arguments-000-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+[PASS] 0-valued - inline
+[PASS] Font relative units - inline
+[PASS] View relative units - inline
+[PASS] Fixed units - inline
+[PASS] Percentage units - inline
+[PASS] 0-valued - computed
+[FAIL] Font relative units - computed
+  assert_equals: expected "polygon(16px 12.8px, 16px 16px)" but got "polygon(16px 8px, 8px 16px)"
+[PASS] View relative units - computed
+[PASS] Fixed units - computed
+[PASS] Percentage units - computed
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-tables/tentative/baseline-table-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-tables/tentative/baseline-table-expected.txt
new file mode 100644
index 0000000..61d3266
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-tables/tentative/baseline-table-expected.txt
@@ -0,0 +1,27 @@
+This is a testharness.js-based test.
+[FAIL] .container 1
+  assert_equals: \n<div class="container">\n  Xp<table data-offset-y="10">\n  </table>\n</div>\noffsetTop expected 10 but got 12
+[FAIL] .container 2
+  assert_equals: \n<div class="container">\n  Xp<table data-offset-y="10">\n    <tbody>\n    </tbody>\n  </table>\n</div>\noffsetTop expected 10 but got 12
+[FAIL] .container 3
+  assert_equals: \n<div class="container">\n  Xp<table data-offset-y="25">\n    <tbody>\n      <tr></tr>\n    </tbody>\n  </table>\n</div>\noffsetTop expected 25 but got 27
+[FAIL] .container 4
+  assert_equals: \n<div class="container">\n  Xp<table style="font: 12px fixed" data-offset-y="25">\n    <tbody>\n      <tr></tr>\n      <tr><td>1,0</td></tr>\n    </tbody>\n  </table>\n</div>\noffsetTop expected 25 but got 27
+[FAIL] .container 5
+  assert_equals: \n<div class="container">\n  Xp<table style="font-size: 24px" data-offset-y="2">\n    <tbody>\n      <tr><td style="vertical-align:baseline">Xp</td></tr>\n    </tbody>\n  </table></div>\noffsetTop expected 2 but got 3
+[PASS] .container 6
+[PASS] .container 7
+[FAIL] .container 8
+  assert_equals: \n<div class="container">\n  Xp<table style="vertical-align:middle" data-offset-y="5"></table>\n</div>\noffsetTop expected 5 but got 16
+[PASS] .container 9
+[FAIL] .container 10
+  assert_equals: \n<div class="container">\n  Xp<table style="vertical-align:top" data-offset-y="0"></table>\n  <table style="vertical-align:middle" data-offset-y="5"></table>\n  <table style="vertical-align:bottom" data-offset-y="20"></table>\n</div>\noffsetTop expected 5 but got 16
+[FAIL] .container 11
+  assert_equals: \n<div class="container">\n  Xp<table data-offset-y="25" data-expected-height="50">\n    <tbody><tr style="height:20px"></tr>\n    <tr></tr>\n  </tbody></table>\n</div>\noffsetTop expected 25 but got 27
+[FAIL] .container 12
+  assert_equals: \n<div class="container">\n  Xp<table data-offset-y="25" data-expected-height="68">\n    <tbody><tr style="height:20px"></tr>\n    <tr><td style="font-size:10px">X</td></tr>\n  </tbody></table>\n</div>\noffsetTop expected 25 but got 27
+[FAIL] .container 13
+  assert_equals: \n<div class="container">\n  Xp<table>\n    <tbody><tr>\n      <td rowspan="2" style="height:80px"></td>\n      <td></td>\n    </tr>\n    <tr>\n      <td></td>\n    </tr>\n  </tbody></table><div style="display:inline-block" data-offset-y="15">pX</div>\n</div>\noffsetTop expected 15 but got 13
+[PASS] .container 14
+[PASS] .container 15
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-tables/tentative/baseline-td-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-tables/tentative/baseline-td-expected.txt
new file mode 100644
index 0000000..d7b0b27
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-tables/tentative/baseline-td-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+[FAIL] table, .display-table 1
+  assert_equals: \n<table style="height:100px" class="ahem vgrad">\n  <tbody><tr><td style="font: 75px/1 Ahem;vertical-align:baseline;"><div class="m" data-offset-y="0">Xp</div></td>\n  <td style="" title="default"><div class="m" data-offset-y="25">Xp</div></td>\n  <td style="vertical-align: top"><div class="m" data-offset-y="0">Xp</div></td>\n  <td style="vertical-align: middle"><div class="m" data-offset-y="25">Xp</div></td>\n  <td style="vertical-align: bottom"><div class="m" data-offset-y="50">Xp</div></td>\n  <td style="vertical-align: baseline"><div class="m" data-offset-y="28">Xp</div></td>\n  <td style="vertical-align: sub"><div class="m" data-offset-y="28">Xp</div></td>\n  <td style="vertical-align: super"><div class="m" data-offset-y="28">Xp</div></td>\n  <td style="vertical-align: text-top"><div class="m" data-offset-y="28">Xp</div></td>\n  <td style="vertical-align: text-bottom"><div class="m" data-offset-y="28">Xp</div></td>\n  <td style="vertical-align: 100px"><div class="m" data-offset-y="28">Xp</div></td>\n  <td style="vertical-align: 100%"><div class="m" data-offset-y="28">Xp</div></td>\n</tr></tbody></table>\noffsetTop expected 28 but got 30
+[FAIL] table, .display-table 2
+  assert_equals: \n<div style="height:100px;position:relative" class="ahem vgrad display-table">\n  <div class="display-cell" style="font: 75px/1 Ahem;vertical-align:baseline;"><div class="m" data-offset-y="0">Xp</div></div>\n  <div class="display-cell" style="" title="default"><div class="m" data-offset-y="28">Xp</div></div>\n  <div class="display-cell" style="vertical-align: top"><div class="m" data-offset-y="0">Xp</div></div>\n  <div class="display-cell" style="vertical-align: middle"><div class="m" data-offset-y="25">Xp</div></div>\n  <div class="display-cell" style="vertical-align: bottom"><div class="m" data-offset-y="50">Xp</div></div>\n  <div class="display-cell" style="vertical-align: baseline"><div class="m" data-offset-y="28">Xp</div></div>\n  <div class="display-cell" style="vertical-align: sub"><div class="m" data-offset-y="28">Xp</div></div>\n  <div class="display-cell" style="vertical-align: super"><div class="m" data-offset-y="28">Xp</div></div>\n  <div class="display-cell" style="vertical-align: text-top"><div class="m" data-offset-y="28">Xp</div></div>\n  <div class="display-cell" style="vertical-align: text-bottom"><div class="m" data-offset-y="28">Xp</div></div>\n  <div class="display-cell" style="vertical-align: 100px"><div class="m" data-offset-y="28">Xp</div></div>\n  <div class="display-cell" style="vertical-align: 100%"><div class="m" data-offset-y="28">Xp</div></div>\n</div>\noffsetTop expected 28 but got 30
+[PASS] table, .display-table 3
+[PASS] table, .display-table 4
+[PASS] table, .display-table 5
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-tables/tentative/table-quirks-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-tables/tentative/table-quirks-expected.txt
new file mode 100644
index 0000000..132e36a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-tables/tentative/table-quirks-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+[PASS] decoration does not propagate into table
+[PASS] table 1
+[PASS] table 2
+[FAIL] table 3
+  assert_equals: \n<table>\n  <tbody><tr>\n    <td nowrap="" style="width:50px;font: 20px/1 Ahem" data-expected-width="580">nowrap nowrap nowrap nowrap</td>\n  </tr>\n</tbody></table>\nwidth expected 580 but got 295
+[PASS] table 4
+[PASS] table 5
+[PASS] table 6
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-text/tab-size/tab-size-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-text/tab-size/tab-size-expected.txt
new file mode 100644
index 0000000..be28941
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-text/tab-size/tab-size-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test tab-size measurements
+  assert_approx_equals: expected 4.03125 +/- 0.02 but got 23.40625
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-text/white-space/trailing-space-position-001-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-text/white-space/trailing-space-position-001-expected.txt
new file mode 100644
index 0000000..8ad73e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-text/white-space/trailing-space-position-001-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+[FAIL] CSS Test: Positions of trailing collapsible spaces
+  assert_equals: expected 0 but got -0
+[FAIL] CSS Test: Positions of trailing collapsible spaces 1
+  assert_equals: expected 0 but got -0
+[FAIL] CSS Test: Positions of trailing collapsible spaces 2
+  assert_equals: expected 0 but got -0
+[FAIL] CSS Test: Positions of trailing collapsible spaces 3
+  assert_equals: expected 0 but got -0
+[FAIL] CSS Test: Positions of trailing collapsible spaces 4
+  assert_equals: expected 0 but got -0
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-ui/appearance-cssom-001-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-ui/appearance-cssom-001-expected.txt
new file mode 100644
index 0000000..bb3c699d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-ui/appearance-cssom-001-expected.txt
@@ -0,0 +1,315 @@
+This is a testharness.js-based test.
+Found 300 tests; 288 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] -webkit-appearance: bogus-button (invalid)
+[PASS] -webkit-appearance: attachment (invalid)
+[PASS] -webkit-appearance: button-bevel (invalid)
+[PASS] -webkit-appearance: borderless-attachment (invalid)
+[PASS] -webkit-appearance: button-arrow-down (invalid)
+[PASS] -webkit-appearance: button-arrow-next (invalid)
+[PASS] -webkit-appearance: button-arrow-previous (invalid)
+[PASS] -webkit-appearance: button-arrow-up (invalid)
+[PASS] -webkit-appearance: button-focus (invalid)
+[PASS] -webkit-appearance: caps-lock-indicator (invalid)
+[PASS] -webkit-appearance: caret (invalid)
+[PASS] -webkit-appearance: checkbox-container (invalid)
+[PASS] -webkit-appearance: checkbox-label (invalid)
+[PASS] -webkit-appearance: checkmenuitem (invalid)
+[PASS] -webkit-appearance: color-well (invalid)
+[PASS] -webkit-appearance: continuous-capacity-level-indicator (invalid)
+[PASS] -webkit-appearance: default-button (invalid)
+[PASS] -webkit-appearance: discrete-capacity-level-indicator (invalid)
+[PASS] -webkit-appearance: dualbutton (invalid)
+[PASS] -webkit-appearance: groupbox (invalid)
+[PASS] -webkit-appearance: image-controls-button (invalid)
+[FAIL] -webkit-appearance: inner-spin-button (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "inner-spin-button" not in array [""]
+[PASS] -webkit-appearance: list-button (invalid)
+[PASS] -webkit-appearance: listitem (invalid)
+[PASS] -webkit-appearance: media-controls-background (invalid)
+[PASS] -webkit-appearance: media-controls-dark-bar-background (invalid)
+[PASS] -webkit-appearance: media-controls-fullscreen-background (invalid)
+[PASS] -webkit-appearance: media-controls-light-bar-background (invalid)
+[PASS] -webkit-appearance: media-current-time-display (invalid)
+[PASS] -webkit-appearance: media-enter-fullscreen-button (invalid)
+[PASS] -webkit-appearance: media-exit-fullscreen-button (invalid)
+[PASS] -webkit-appearance: media-fullscreen-volume-slider (invalid)
+[PASS] -webkit-appearance: media-fullscreen-volume-slider-thumb (invalid)
+[PASS] -webkit-appearance: media-mute-button (invalid)
+[PASS] -webkit-appearance: media-overlay-play-button (invalid)
+[PASS] -webkit-appearance: media-play-button (invalid)
+[PASS] -webkit-appearance: media-return-to-realtime-button (invalid)
+[PASS] -webkit-appearance: media-rewind-button (invalid)
+[PASS] -webkit-appearance: media-seek-back-button (invalid)
+[PASS] -webkit-appearance: media-seek-forward-button (invalid)
+[PASS] -webkit-appearance: media-slider (invalid)
+[PASS] -webkit-appearance: media-sliderthumb (invalid)
+[PASS] -webkit-appearance: media-time-remaining-display (invalid)
+[PASS] -webkit-appearance: media-toggle-closed-captions-button (invalid)
+[PASS] -webkit-appearance: media-volume-slider (invalid)
+[PASS] -webkit-appearance: media-volume-slider-container (invalid)
+[PASS] -webkit-appearance: media-volume-slider-mute-button (invalid)
+[PASS] -webkit-appearance: media-volume-sliderthumb (invalid)
+[PASS] -webkit-appearance: menuarrow (invalid)
+[PASS] -webkit-appearance: menubar (invalid)
+[PASS] -webkit-appearance: menucheckbox (invalid)
+[PASS] -webkit-appearance: menuimage (invalid)
+[PASS] -webkit-appearance: menuitem (invalid)
+[PASS] -webkit-appearance: menuitemtext (invalid)
+[PASS] -webkit-appearance: menulist-text (invalid)
+[PASS] -webkit-appearance: menulist-textfield (invalid)
+[PASS] -webkit-appearance: menupopup (invalid)
+[PASS] -webkit-appearance: menuradio (invalid)
+[PASS] -webkit-appearance: menuseparator (invalid)
+[PASS] -webkit-appearance: meterbar (invalid)
+[PASS] -webkit-appearance: meterchunk (invalid)
+[PASS] -webkit-appearance: number-input (invalid)
+[PASS] -webkit-appearance: progress-bar-value (invalid)
+[PASS] -webkit-appearance: progressbar (invalid)
+[PASS] -webkit-appearance: progressbar-vertical (invalid)
+[PASS] -webkit-appearance: progresschunk (invalid)
+[PASS] -webkit-appearance: progresschunk-vertical (invalid)
+[FAIL] -webkit-appearance: push-button (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "push-button" not in array [""]
+[PASS] -webkit-appearance: radio-container (invalid)
+[PASS] -webkit-appearance: radio-label (invalid)
+[PASS] -webkit-appearance: radiomenuitem (invalid)
+[PASS] -webkit-appearance: range (invalid)
+[PASS] -webkit-appearance: range-thumb (invalid)
+[PASS] -webkit-appearance: rating-level-indicator (invalid)
+[PASS] -webkit-appearance: relevancy-level-indicator (invalid)
+[PASS] -webkit-appearance: resizer (invalid)
+[PASS] -webkit-appearance: resizerpanel (invalid)
+[PASS] -webkit-appearance: scale-horizontal (invalid)
+[PASS] -webkit-appearance: scale-vertical (invalid)
+[PASS] -webkit-appearance: scalethumb-horizontal (invalid)
+[PASS] -webkit-appearance: scalethumb-vertical (invalid)
+[PASS] -webkit-appearance: scalethumbend (invalid)
+[PASS] -webkit-appearance: scalethumbstart (invalid)
+[PASS] -webkit-appearance: scalethumbtick (invalid)
+[PASS] -webkit-appearance: scrollbarbutton-down (invalid)
+[PASS] -webkit-appearance: scrollbarbutton-left (invalid)
+[PASS] -webkit-appearance: scrollbarbutton-right (invalid)
+[PASS] -webkit-appearance: scrollbarbutton-up (invalid)
+[PASS] -webkit-appearance: scrollbarthumb-horizontal (invalid)
+[PASS] -webkit-appearance: scrollbarthumb-vertical (invalid)
+[PASS] -webkit-appearance: scrollbartrack-horizontal (invalid)
+[PASS] -webkit-appearance: scrollbartrack-vertical (invalid)
+[FAIL] -webkit-appearance: searchfield-cancel-button (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "searchfield-cancel-button" not in array [""]
+[PASS] -webkit-appearance: searchfield-decoration (invalid)
+[PASS] -webkit-appearance: searchfield-results-button (invalid)
+[PASS] -webkit-appearance: searchfield-results-decoration (invalid)
+[PASS] -webkit-appearance: separator (invalid)
+[PASS] -webkit-appearance: sheet (invalid)
+[FAIL] -webkit-appearance: slider-horizontal (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "slider-horizontal" not in array [""]
+[FAIL] -webkit-appearance: slider-vertical (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "slider-vertical" not in array [""]
+[PASS] -webkit-appearance: sliderthumb-horizontal (invalid)
+[PASS] -webkit-appearance: sliderthumb-vertical (invalid)
+[PASS] -webkit-appearance: snapshotted-plugin-overlay (invalid)
+[PASS] -webkit-appearance: spinner (invalid)
+[PASS] -webkit-appearance: spinner-downbutton (invalid)
+[PASS] -webkit-appearance: spinner-textfield (invalid)
+[PASS] -webkit-appearance: spinner-upbutton (invalid)
+[PASS] -webkit-appearance: splitter (invalid)
+[FAIL] -webkit-appearance: square-button (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "square-button" not in array [""]
+[PASS] -webkit-appearance: statusbar (invalid)
+[PASS] -webkit-appearance: statusbarpanel (invalid)
+[PASS] -webkit-appearance: tab (invalid)
+[PASS] -webkit-appearance: tab-scroll-arrow-back (invalid)
+[PASS] -webkit-appearance: tab-scroll-arrow-forward (invalid)
+[PASS] -webkit-appearance: tabpanel (invalid)
+[PASS] -webkit-appearance: tabpanels (invalid)
+[PASS] -webkit-appearance: textfield-multiline (invalid)
+[PASS] -webkit-appearance: toolbar (invalid)
+[PASS] -webkit-appearance: toolbarbutton (invalid)
+[PASS] -webkit-appearance: toolbarbutton-dropdown (invalid)
+[PASS] -webkit-appearance: toolbargripper (invalid)
+[PASS] -webkit-appearance: toolbox (invalid)
+[PASS] -webkit-appearance: tooltip (invalid)
+[PASS] -webkit-appearance: treeheader (invalid)
+[PASS] -webkit-appearance: treeheadercell (invalid)
+[PASS] -webkit-appearance: treeheadersortarrow (invalid)
+[PASS] -webkit-appearance: treeitem (invalid)
+[PASS] -webkit-appearance: treeline (invalid)
+[PASS] -webkit-appearance: treetwisty (invalid)
+[PASS] -webkit-appearance: treetwistyopen (invalid)
+[PASS] -webkit-appearance: treeview (invalid)
+[PASS] -webkit-appearance: -apple-pay-button (invalid)
+[PASS] -webkit-appearance: -moz-win-borderless-glass (invalid)
+[PASS] -webkit-appearance: -moz-win-browsertabbar-toolbox (invalid)
+[PASS] -webkit-appearance: -moz-win-communications-toolbox (invalid)
+[PASS] -webkit-appearance: -moz-win-communicationstext (invalid)
+[PASS] -webkit-appearance: -moz-win-exclude-glass (invalid)
+[PASS] -webkit-appearance: -moz-win-glass (invalid)
+[PASS] -webkit-appearance: -moz-win-media-toolbox (invalid)
+[PASS] -webkit-appearance: -moz-window-button-box (invalid)
+[PASS] -webkit-appearance: -moz-window-button-box-maximized (invalid)
+[PASS] -webkit-appearance: -moz-window-button-close (invalid)
+[PASS] -webkit-appearance: -moz-window-button-maximize (invalid)
+[PASS] -webkit-appearance: -moz-window-button-minimize (invalid)
+[PASS] -webkit-appearance: -moz-window-button-restore (invalid)
+[PASS] -webkit-appearance: -moz-window-frame-bottom (invalid)
+[PASS] -webkit-appearance: -moz-window-frame-left (invalid)
+[PASS] -webkit-appearance: -moz-window-frame-right (invalid)
+[PASS] -webkit-appearance: -moz-window-titlebar (invalid)
+[PASS] -webkit-appearance: -moz-window-titlebar-maximized (invalid)
+[PASS] appearance: bogus-button (invalid)
+[PASS] appearance: attachment (invalid)
+[PASS] appearance: button-bevel (invalid)
+[PASS] appearance: borderless-attachment (invalid)
+[PASS] appearance: button-arrow-down (invalid)
+[PASS] appearance: button-arrow-next (invalid)
+[PASS] appearance: button-arrow-previous (invalid)
+[PASS] appearance: button-arrow-up (invalid)
+[PASS] appearance: button-focus (invalid)
+[PASS] appearance: caps-lock-indicator (invalid)
+[PASS] appearance: caret (invalid)
+[PASS] appearance: checkbox-container (invalid)
+[PASS] appearance: checkbox-label (invalid)
+[PASS] appearance: checkmenuitem (invalid)
+[PASS] appearance: color-well (invalid)
+[PASS] appearance: continuous-capacity-level-indicator (invalid)
+[PASS] appearance: default-button (invalid)
+[PASS] appearance: discrete-capacity-level-indicator (invalid)
+[PASS] appearance: dualbutton (invalid)
+[PASS] appearance: groupbox (invalid)
+[PASS] appearance: image-controls-button (invalid)
+[FAIL] appearance: inner-spin-button (invalid)
+  assert_in_array: style.appearance value "inner-spin-button" not in array [""]
+[PASS] appearance: list-button (invalid)
+[PASS] appearance: listitem (invalid)
+[PASS] appearance: media-controls-background (invalid)
+[PASS] appearance: media-controls-dark-bar-background (invalid)
+[PASS] appearance: media-controls-fullscreen-background (invalid)
+[PASS] appearance: media-controls-light-bar-background (invalid)
+[PASS] appearance: media-current-time-display (invalid)
+[PASS] appearance: media-enter-fullscreen-button (invalid)
+[PASS] appearance: media-exit-fullscreen-button (invalid)
+[PASS] appearance: media-fullscreen-volume-slider (invalid)
+[PASS] appearance: media-fullscreen-volume-slider-thumb (invalid)
+[PASS] appearance: media-mute-button (invalid)
+[PASS] appearance: media-overlay-play-button (invalid)
+[PASS] appearance: media-play-button (invalid)
+[PASS] appearance: media-return-to-realtime-button (invalid)
+[PASS] appearance: media-rewind-button (invalid)
+[PASS] appearance: media-seek-back-button (invalid)
+[PASS] appearance: media-seek-forward-button (invalid)
+[PASS] appearance: media-slider (invalid)
+[PASS] appearance: media-sliderthumb (invalid)
+[PASS] appearance: media-time-remaining-display (invalid)
+[PASS] appearance: media-toggle-closed-captions-button (invalid)
+[PASS] appearance: media-volume-slider (invalid)
+[PASS] appearance: media-volume-slider-container (invalid)
+[PASS] appearance: media-volume-slider-mute-button (invalid)
+[PASS] appearance: media-volume-sliderthumb (invalid)
+[PASS] appearance: menuarrow (invalid)
+[PASS] appearance: menubar (invalid)
+[PASS] appearance: menucheckbox (invalid)
+[PASS] appearance: menuimage (invalid)
+[PASS] appearance: menuitem (invalid)
+[PASS] appearance: menuitemtext (invalid)
+[PASS] appearance: menulist-text (invalid)
+[PASS] appearance: menulist-textfield (invalid)
+[PASS] appearance: menupopup (invalid)
+[PASS] appearance: menuradio (invalid)
+[PASS] appearance: menuseparator (invalid)
+[PASS] appearance: meterbar (invalid)
+[PASS] appearance: meterchunk (invalid)
+[PASS] appearance: number-input (invalid)
+[PASS] appearance: progress-bar-value (invalid)
+[PASS] appearance: progressbar (invalid)
+[PASS] appearance: progressbar-vertical (invalid)
+[PASS] appearance: progresschunk (invalid)
+[PASS] appearance: progresschunk-vertical (invalid)
+[FAIL] appearance: push-button (invalid)
+  assert_in_array: style.appearance value "push-button" not in array [""]
+[PASS] appearance: radio-container (invalid)
+[PASS] appearance: radio-label (invalid)
+[PASS] appearance: radiomenuitem (invalid)
+[PASS] appearance: range (invalid)
+[PASS] appearance: range-thumb (invalid)
+[PASS] appearance: rating-level-indicator (invalid)
+[PASS] appearance: relevancy-level-indicator (invalid)
+[PASS] appearance: resizer (invalid)
+[PASS] appearance: resizerpanel (invalid)
+[PASS] appearance: scale-horizontal (invalid)
+[PASS] appearance: scale-vertical (invalid)
+[PASS] appearance: scalethumb-horizontal (invalid)
+[PASS] appearance: scalethumb-vertical (invalid)
+[PASS] appearance: scalethumbend (invalid)
+[PASS] appearance: scalethumbstart (invalid)
+[PASS] appearance: scalethumbtick (invalid)
+[PASS] appearance: scrollbarbutton-down (invalid)
+[PASS] appearance: scrollbarbutton-left (invalid)
+[PASS] appearance: scrollbarbutton-right (invalid)
+[PASS] appearance: scrollbarbutton-up (invalid)
+[PASS] appearance: scrollbarthumb-horizontal (invalid)
+[PASS] appearance: scrollbarthumb-vertical (invalid)
+[PASS] appearance: scrollbartrack-horizontal (invalid)
+[PASS] appearance: scrollbartrack-vertical (invalid)
+[FAIL] appearance: searchfield-cancel-button (invalid)
+  assert_in_array: style.appearance value "searchfield-cancel-button" not in array [""]
+[PASS] appearance: searchfield-decoration (invalid)
+[PASS] appearance: searchfield-results-button (invalid)
+[PASS] appearance: searchfield-results-decoration (invalid)
+[PASS] appearance: separator (invalid)
+[PASS] appearance: sheet (invalid)
+[FAIL] appearance: slider-horizontal (invalid)
+  assert_in_array: style.appearance value "slider-horizontal" not in array [""]
+[FAIL] appearance: slider-vertical (invalid)
+  assert_in_array: style.appearance value "slider-vertical" not in array [""]
+[PASS] appearance: sliderthumb-horizontal (invalid)
+[PASS] appearance: sliderthumb-vertical (invalid)
+[PASS] appearance: snapshotted-plugin-overlay (invalid)
+[PASS] appearance: spinner (invalid)
+[PASS] appearance: spinner-downbutton (invalid)
+[PASS] appearance: spinner-textfield (invalid)
+[PASS] appearance: spinner-upbutton (invalid)
+[PASS] appearance: splitter (invalid)
+[FAIL] appearance: square-button (invalid)
+  assert_in_array: style.appearance value "square-button" not in array [""]
+[PASS] appearance: statusbar (invalid)
+[PASS] appearance: statusbarpanel (invalid)
+[PASS] appearance: tab (invalid)
+[PASS] appearance: tab-scroll-arrow-back (invalid)
+[PASS] appearance: tab-scroll-arrow-forward (invalid)
+[PASS] appearance: tabpanel (invalid)
+[PASS] appearance: tabpanels (invalid)
+[PASS] appearance: textfield-multiline (invalid)
+[PASS] appearance: toolbar (invalid)
+[PASS] appearance: toolbarbutton (invalid)
+[PASS] appearance: toolbarbutton-dropdown (invalid)
+[PASS] appearance: toolbargripper (invalid)
+[PASS] appearance: toolbox (invalid)
+[PASS] appearance: tooltip (invalid)
+[PASS] appearance: treeheader (invalid)
+[PASS] appearance: treeheadercell (invalid)
+[PASS] appearance: treeheadersortarrow (invalid)
+[PASS] appearance: treeitem (invalid)
+[PASS] appearance: treeline (invalid)
+[PASS] appearance: treetwisty (invalid)
+[PASS] appearance: treetwistyopen (invalid)
+[PASS] appearance: treeview (invalid)
+[PASS] appearance: -apple-pay-button (invalid)
+[PASS] appearance: -moz-win-borderless-glass (invalid)
+[PASS] appearance: -moz-win-browsertabbar-toolbox (invalid)
+[PASS] appearance: -moz-win-communications-toolbox (invalid)
+[PASS] appearance: -moz-win-communicationstext (invalid)
+[PASS] appearance: -moz-win-exclude-glass (invalid)
+[PASS] appearance: -moz-win-glass (invalid)
+[PASS] appearance: -moz-win-media-toolbox (invalid)
+[PASS] appearance: -moz-window-button-box (invalid)
+[PASS] appearance: -moz-window-button-box-maximized (invalid)
+[PASS] appearance: -moz-window-button-close (invalid)
+[PASS] appearance: -moz-window-button-maximize (invalid)
+[PASS] appearance: -moz-window-button-minimize (invalid)
+[PASS] appearance: -moz-window-button-restore (invalid)
+[PASS] appearance: -moz-window-frame-bottom (invalid)
+[PASS] appearance: -moz-window-frame-left (invalid)
+[PASS] appearance: -moz-window-frame-right (invalid)
+[PASS] appearance: -moz-window-titlebar (invalid)
+[PASS] appearance: -moz-window-titlebar-maximized (invalid)
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-ui/appearance-cssom-001_include=Invalid-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-ui/appearance-cssom-001_include=Invalid-expected.txt
new file mode 100644
index 0000000..bb3c699d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/css-ui/appearance-cssom-001_include=Invalid-expected.txt
@@ -0,0 +1,315 @@
+This is a testharness.js-based test.
+Found 300 tests; 288 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] -webkit-appearance: bogus-button (invalid)
+[PASS] -webkit-appearance: attachment (invalid)
+[PASS] -webkit-appearance: button-bevel (invalid)
+[PASS] -webkit-appearance: borderless-attachment (invalid)
+[PASS] -webkit-appearance: button-arrow-down (invalid)
+[PASS] -webkit-appearance: button-arrow-next (invalid)
+[PASS] -webkit-appearance: button-arrow-previous (invalid)
+[PASS] -webkit-appearance: button-arrow-up (invalid)
+[PASS] -webkit-appearance: button-focus (invalid)
+[PASS] -webkit-appearance: caps-lock-indicator (invalid)
+[PASS] -webkit-appearance: caret (invalid)
+[PASS] -webkit-appearance: checkbox-container (invalid)
+[PASS] -webkit-appearance: checkbox-label (invalid)
+[PASS] -webkit-appearance: checkmenuitem (invalid)
+[PASS] -webkit-appearance: color-well (invalid)
+[PASS] -webkit-appearance: continuous-capacity-level-indicator (invalid)
+[PASS] -webkit-appearance: default-button (invalid)
+[PASS] -webkit-appearance: discrete-capacity-level-indicator (invalid)
+[PASS] -webkit-appearance: dualbutton (invalid)
+[PASS] -webkit-appearance: groupbox (invalid)
+[PASS] -webkit-appearance: image-controls-button (invalid)
+[FAIL] -webkit-appearance: inner-spin-button (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "inner-spin-button" not in array [""]
+[PASS] -webkit-appearance: list-button (invalid)
+[PASS] -webkit-appearance: listitem (invalid)
+[PASS] -webkit-appearance: media-controls-background (invalid)
+[PASS] -webkit-appearance: media-controls-dark-bar-background (invalid)
+[PASS] -webkit-appearance: media-controls-fullscreen-background (invalid)
+[PASS] -webkit-appearance: media-controls-light-bar-background (invalid)
+[PASS] -webkit-appearance: media-current-time-display (invalid)
+[PASS] -webkit-appearance: media-enter-fullscreen-button (invalid)
+[PASS] -webkit-appearance: media-exit-fullscreen-button (invalid)
+[PASS] -webkit-appearance: media-fullscreen-volume-slider (invalid)
+[PASS] -webkit-appearance: media-fullscreen-volume-slider-thumb (invalid)
+[PASS] -webkit-appearance: media-mute-button (invalid)
+[PASS] -webkit-appearance: media-overlay-play-button (invalid)
+[PASS] -webkit-appearance: media-play-button (invalid)
+[PASS] -webkit-appearance: media-return-to-realtime-button (invalid)
+[PASS] -webkit-appearance: media-rewind-button (invalid)
+[PASS] -webkit-appearance: media-seek-back-button (invalid)
+[PASS] -webkit-appearance: media-seek-forward-button (invalid)
+[PASS] -webkit-appearance: media-slider (invalid)
+[PASS] -webkit-appearance: media-sliderthumb (invalid)
+[PASS] -webkit-appearance: media-time-remaining-display (invalid)
+[PASS] -webkit-appearance: media-toggle-closed-captions-button (invalid)
+[PASS] -webkit-appearance: media-volume-slider (invalid)
+[PASS] -webkit-appearance: media-volume-slider-container (invalid)
+[PASS] -webkit-appearance: media-volume-slider-mute-button (invalid)
+[PASS] -webkit-appearance: media-volume-sliderthumb (invalid)
+[PASS] -webkit-appearance: menuarrow (invalid)
+[PASS] -webkit-appearance: menubar (invalid)
+[PASS] -webkit-appearance: menucheckbox (invalid)
+[PASS] -webkit-appearance: menuimage (invalid)
+[PASS] -webkit-appearance: menuitem (invalid)
+[PASS] -webkit-appearance: menuitemtext (invalid)
+[PASS] -webkit-appearance: menulist-text (invalid)
+[PASS] -webkit-appearance: menulist-textfield (invalid)
+[PASS] -webkit-appearance: menupopup (invalid)
+[PASS] -webkit-appearance: menuradio (invalid)
+[PASS] -webkit-appearance: menuseparator (invalid)
+[PASS] -webkit-appearance: meterbar (invalid)
+[PASS] -webkit-appearance: meterchunk (invalid)
+[PASS] -webkit-appearance: number-input (invalid)
+[PASS] -webkit-appearance: progress-bar-value (invalid)
+[PASS] -webkit-appearance: progressbar (invalid)
+[PASS] -webkit-appearance: progressbar-vertical (invalid)
+[PASS] -webkit-appearance: progresschunk (invalid)
+[PASS] -webkit-appearance: progresschunk-vertical (invalid)
+[FAIL] -webkit-appearance: push-button (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "push-button" not in array [""]
+[PASS] -webkit-appearance: radio-container (invalid)
+[PASS] -webkit-appearance: radio-label (invalid)
+[PASS] -webkit-appearance: radiomenuitem (invalid)
+[PASS] -webkit-appearance: range (invalid)
+[PASS] -webkit-appearance: range-thumb (invalid)
+[PASS] -webkit-appearance: rating-level-indicator (invalid)
+[PASS] -webkit-appearance: relevancy-level-indicator (invalid)
+[PASS] -webkit-appearance: resizer (invalid)
+[PASS] -webkit-appearance: resizerpanel (invalid)
+[PASS] -webkit-appearance: scale-horizontal (invalid)
+[PASS] -webkit-appearance: scale-vertical (invalid)
+[PASS] -webkit-appearance: scalethumb-horizontal (invalid)
+[PASS] -webkit-appearance: scalethumb-vertical (invalid)
+[PASS] -webkit-appearance: scalethumbend (invalid)
+[PASS] -webkit-appearance: scalethumbstart (invalid)
+[PASS] -webkit-appearance: scalethumbtick (invalid)
+[PASS] -webkit-appearance: scrollbarbutton-down (invalid)
+[PASS] -webkit-appearance: scrollbarbutton-left (invalid)
+[PASS] -webkit-appearance: scrollbarbutton-right (invalid)
+[PASS] -webkit-appearance: scrollbarbutton-up (invalid)
+[PASS] -webkit-appearance: scrollbarthumb-horizontal (invalid)
+[PASS] -webkit-appearance: scrollbarthumb-vertical (invalid)
+[PASS] -webkit-appearance: scrollbartrack-horizontal (invalid)
+[PASS] -webkit-appearance: scrollbartrack-vertical (invalid)
+[FAIL] -webkit-appearance: searchfield-cancel-button (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "searchfield-cancel-button" not in array [""]
+[PASS] -webkit-appearance: searchfield-decoration (invalid)
+[PASS] -webkit-appearance: searchfield-results-button (invalid)
+[PASS] -webkit-appearance: searchfield-results-decoration (invalid)
+[PASS] -webkit-appearance: separator (invalid)
+[PASS] -webkit-appearance: sheet (invalid)
+[FAIL] -webkit-appearance: slider-horizontal (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "slider-horizontal" not in array [""]
+[FAIL] -webkit-appearance: slider-vertical (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "slider-vertical" not in array [""]
+[PASS] -webkit-appearance: sliderthumb-horizontal (invalid)
+[PASS] -webkit-appearance: sliderthumb-vertical (invalid)
+[PASS] -webkit-appearance: snapshotted-plugin-overlay (invalid)
+[PASS] -webkit-appearance: spinner (invalid)
+[PASS] -webkit-appearance: spinner-downbutton (invalid)
+[PASS] -webkit-appearance: spinner-textfield (invalid)
+[PASS] -webkit-appearance: spinner-upbutton (invalid)
+[PASS] -webkit-appearance: splitter (invalid)
+[FAIL] -webkit-appearance: square-button (invalid)
+  assert_in_array: style.WebkitAppearance (uppercase W) value "square-button" not in array [""]
+[PASS] -webkit-appearance: statusbar (invalid)
+[PASS] -webkit-appearance: statusbarpanel (invalid)
+[PASS] -webkit-appearance: tab (invalid)
+[PASS] -webkit-appearance: tab-scroll-arrow-back (invalid)
+[PASS] -webkit-appearance: tab-scroll-arrow-forward (invalid)
+[PASS] -webkit-appearance: tabpanel (invalid)
+[PASS] -webkit-appearance: tabpanels (invalid)
+[PASS] -webkit-appearance: textfield-multiline (invalid)
+[PASS] -webkit-appearance: toolbar (invalid)
+[PASS] -webkit-appearance: toolbarbutton (invalid)
+[PASS] -webkit-appearance: toolbarbutton-dropdown (invalid)
+[PASS] -webkit-appearance: toolbargripper (invalid)
+[PASS] -webkit-appearance: toolbox (invalid)
+[PASS] -webkit-appearance: tooltip (invalid)
+[PASS] -webkit-appearance: treeheader (invalid)
+[PASS] -webkit-appearance: treeheadercell (invalid)
+[PASS] -webkit-appearance: treeheadersortarrow (invalid)
+[PASS] -webkit-appearance: treeitem (invalid)
+[PASS] -webkit-appearance: treeline (invalid)
+[PASS] -webkit-appearance: treetwisty (invalid)
+[PASS] -webkit-appearance: treetwistyopen (invalid)
+[PASS] -webkit-appearance: treeview (invalid)
+[PASS] -webkit-appearance: -apple-pay-button (invalid)
+[PASS] -webkit-appearance: -moz-win-borderless-glass (invalid)
+[PASS] -webkit-appearance: -moz-win-browsertabbar-toolbox (invalid)
+[PASS] -webkit-appearance: -moz-win-communications-toolbox (invalid)
+[PASS] -webkit-appearance: -moz-win-communicationstext (invalid)
+[PASS] -webkit-appearance: -moz-win-exclude-glass (invalid)
+[PASS] -webkit-appearance: -moz-win-glass (invalid)
+[PASS] -webkit-appearance: -moz-win-media-toolbox (invalid)
+[PASS] -webkit-appearance: -moz-window-button-box (invalid)
+[PASS] -webkit-appearance: -moz-window-button-box-maximized (invalid)
+[PASS] -webkit-appearance: -moz-window-button-close (invalid)
+[PASS] -webkit-appearance: -moz-window-button-maximize (invalid)
+[PASS] -webkit-appearance: -moz-window-button-minimize (invalid)
+[PASS] -webkit-appearance: -moz-window-button-restore (invalid)
+[PASS] -webkit-appearance: -moz-window-frame-bottom (invalid)
+[PASS] -webkit-appearance: -moz-window-frame-left (invalid)
+[PASS] -webkit-appearance: -moz-window-frame-right (invalid)
+[PASS] -webkit-appearance: -moz-window-titlebar (invalid)
+[PASS] -webkit-appearance: -moz-window-titlebar-maximized (invalid)
+[PASS] appearance: bogus-button (invalid)
+[PASS] appearance: attachment (invalid)
+[PASS] appearance: button-bevel (invalid)
+[PASS] appearance: borderless-attachment (invalid)
+[PASS] appearance: button-arrow-down (invalid)
+[PASS] appearance: button-arrow-next (invalid)
+[PASS] appearance: button-arrow-previous (invalid)
+[PASS] appearance: button-arrow-up (invalid)
+[PASS] appearance: button-focus (invalid)
+[PASS] appearance: caps-lock-indicator (invalid)
+[PASS] appearance: caret (invalid)
+[PASS] appearance: checkbox-container (invalid)
+[PASS] appearance: checkbox-label (invalid)
+[PASS] appearance: checkmenuitem (invalid)
+[PASS] appearance: color-well (invalid)
+[PASS] appearance: continuous-capacity-level-indicator (invalid)
+[PASS] appearance: default-button (invalid)
+[PASS] appearance: discrete-capacity-level-indicator (invalid)
+[PASS] appearance: dualbutton (invalid)
+[PASS] appearance: groupbox (invalid)
+[PASS] appearance: image-controls-button (invalid)
+[FAIL] appearance: inner-spin-button (invalid)
+  assert_in_array: style.appearance value "inner-spin-button" not in array [""]
+[PASS] appearance: list-button (invalid)
+[PASS] appearance: listitem (invalid)
+[PASS] appearance: media-controls-background (invalid)
+[PASS] appearance: media-controls-dark-bar-background (invalid)
+[PASS] appearance: media-controls-fullscreen-background (invalid)
+[PASS] appearance: media-controls-light-bar-background (invalid)
+[PASS] appearance: media-current-time-display (invalid)
+[PASS] appearance: media-enter-fullscreen-button (invalid)
+[PASS] appearance: media-exit-fullscreen-button (invalid)
+[PASS] appearance: media-fullscreen-volume-slider (invalid)
+[PASS] appearance: media-fullscreen-volume-slider-thumb (invalid)
+[PASS] appearance: media-mute-button (invalid)
+[PASS] appearance: media-overlay-play-button (invalid)
+[PASS] appearance: media-play-button (invalid)
+[PASS] appearance: media-return-to-realtime-button (invalid)
+[PASS] appearance: media-rewind-button (invalid)
+[PASS] appearance: media-seek-back-button (invalid)
+[PASS] appearance: media-seek-forward-button (invalid)
+[PASS] appearance: media-slider (invalid)
+[PASS] appearance: media-sliderthumb (invalid)
+[PASS] appearance: media-time-remaining-display (invalid)
+[PASS] appearance: media-toggle-closed-captions-button (invalid)
+[PASS] appearance: media-volume-slider (invalid)
+[PASS] appearance: media-volume-slider-container (invalid)
+[PASS] appearance: media-volume-slider-mute-button (invalid)
+[PASS] appearance: media-volume-sliderthumb (invalid)
+[PASS] appearance: menuarrow (invalid)
+[PASS] appearance: menubar (invalid)
+[PASS] appearance: menucheckbox (invalid)
+[PASS] appearance: menuimage (invalid)
+[PASS] appearance: menuitem (invalid)
+[PASS] appearance: menuitemtext (invalid)
+[PASS] appearance: menulist-text (invalid)
+[PASS] appearance: menulist-textfield (invalid)
+[PASS] appearance: menupopup (invalid)
+[PASS] appearance: menuradio (invalid)
+[PASS] appearance: menuseparator (invalid)
+[PASS] appearance: meterbar (invalid)
+[PASS] appearance: meterchunk (invalid)
+[PASS] appearance: number-input (invalid)
+[PASS] appearance: progress-bar-value (invalid)
+[PASS] appearance: progressbar (invalid)
+[PASS] appearance: progressbar-vertical (invalid)
+[PASS] appearance: progresschunk (invalid)
+[PASS] appearance: progresschunk-vertical (invalid)
+[FAIL] appearance: push-button (invalid)
+  assert_in_array: style.appearance value "push-button" not in array [""]
+[PASS] appearance: radio-container (invalid)
+[PASS] appearance: radio-label (invalid)
+[PASS] appearance: radiomenuitem (invalid)
+[PASS] appearance: range (invalid)
+[PASS] appearance: range-thumb (invalid)
+[PASS] appearance: rating-level-indicator (invalid)
+[PASS] appearance: relevancy-level-indicator (invalid)
+[PASS] appearance: resizer (invalid)
+[PASS] appearance: resizerpanel (invalid)
+[PASS] appearance: scale-horizontal (invalid)
+[PASS] appearance: scale-vertical (invalid)
+[PASS] appearance: scalethumb-horizontal (invalid)
+[PASS] appearance: scalethumb-vertical (invalid)
+[PASS] appearance: scalethumbend (invalid)
+[PASS] appearance: scalethumbstart (invalid)
+[PASS] appearance: scalethumbtick (invalid)
+[PASS] appearance: scrollbarbutton-down (invalid)
+[PASS] appearance: scrollbarbutton-left (invalid)
+[PASS] appearance: scrollbarbutton-right (invalid)
+[PASS] appearance: scrollbarbutton-up (invalid)
+[PASS] appearance: scrollbarthumb-horizontal (invalid)
+[PASS] appearance: scrollbarthumb-vertical (invalid)
+[PASS] appearance: scrollbartrack-horizontal (invalid)
+[PASS] appearance: scrollbartrack-vertical (invalid)
+[FAIL] appearance: searchfield-cancel-button (invalid)
+  assert_in_array: style.appearance value "searchfield-cancel-button" not in array [""]
+[PASS] appearance: searchfield-decoration (invalid)
+[PASS] appearance: searchfield-results-button (invalid)
+[PASS] appearance: searchfield-results-decoration (invalid)
+[PASS] appearance: separator (invalid)
+[PASS] appearance: sheet (invalid)
+[FAIL] appearance: slider-horizontal (invalid)
+  assert_in_array: style.appearance value "slider-horizontal" not in array [""]
+[FAIL] appearance: slider-vertical (invalid)
+  assert_in_array: style.appearance value "slider-vertical" not in array [""]
+[PASS] appearance: sliderthumb-horizontal (invalid)
+[PASS] appearance: sliderthumb-vertical (invalid)
+[PASS] appearance: snapshotted-plugin-overlay (invalid)
+[PASS] appearance: spinner (invalid)
+[PASS] appearance: spinner-downbutton (invalid)
+[PASS] appearance: spinner-textfield (invalid)
+[PASS] appearance: spinner-upbutton (invalid)
+[PASS] appearance: splitter (invalid)
+[FAIL] appearance: square-button (invalid)
+  assert_in_array: style.appearance value "square-button" not in array [""]
+[PASS] appearance: statusbar (invalid)
+[PASS] appearance: statusbarpanel (invalid)
+[PASS] appearance: tab (invalid)
+[PASS] appearance: tab-scroll-arrow-back (invalid)
+[PASS] appearance: tab-scroll-arrow-forward (invalid)
+[PASS] appearance: tabpanel (invalid)
+[PASS] appearance: tabpanels (invalid)
+[PASS] appearance: textfield-multiline (invalid)
+[PASS] appearance: toolbar (invalid)
+[PASS] appearance: toolbarbutton (invalid)
+[PASS] appearance: toolbarbutton-dropdown (invalid)
+[PASS] appearance: toolbargripper (invalid)
+[PASS] appearance: toolbox (invalid)
+[PASS] appearance: tooltip (invalid)
+[PASS] appearance: treeheader (invalid)
+[PASS] appearance: treeheadercell (invalid)
+[PASS] appearance: treeheadersortarrow (invalid)
+[PASS] appearance: treeitem (invalid)
+[PASS] appearance: treeline (invalid)
+[PASS] appearance: treetwisty (invalid)
+[PASS] appearance: treetwistyopen (invalid)
+[PASS] appearance: treeview (invalid)
+[PASS] appearance: -apple-pay-button (invalid)
+[PASS] appearance: -moz-win-borderless-glass (invalid)
+[PASS] appearance: -moz-win-browsertabbar-toolbox (invalid)
+[PASS] appearance: -moz-win-communications-toolbox (invalid)
+[PASS] appearance: -moz-win-communicationstext (invalid)
+[PASS] appearance: -moz-win-exclude-glass (invalid)
+[PASS] appearance: -moz-win-glass (invalid)
+[PASS] appearance: -moz-win-media-toolbox (invalid)
+[PASS] appearance: -moz-window-button-box (invalid)
+[PASS] appearance: -moz-window-button-box-maximized (invalid)
+[PASS] appearance: -moz-window-button-close (invalid)
+[PASS] appearance: -moz-window-button-maximize (invalid)
+[PASS] appearance: -moz-window-button-minimize (invalid)
+[PASS] appearance: -moz-window-button-restore (invalid)
+[PASS] appearance: -moz-window-frame-bottom (invalid)
+[PASS] appearance: -moz-window-frame-left (invalid)
+[PASS] appearance: -moz-window-frame-right (invalid)
+[PASS] appearance: -moz-window-titlebar (invalid)
+[PASS] appearance: -moz-window-titlebar-maximized (invalid)
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom-view/getBoundingClientRect-shy-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom-view/getBoundingClientRect-shy-expected.txt
new file mode 100644
index 0000000..66d2b8bf
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom-view/getBoundingClientRect-shy-expected.txt
@@ -0,0 +1,24 @@
+This is a testharness.js-based test.
+[FAIL] Range 0-5 should not include the hyphen.
+  assert_equals: expected 50 but got 25
+[FAIL] Range 1-5 should not include the hyphen.
+  assert_equals: expected 40 but got 20
+[FAIL] Range 0-6 should not include the hyphen.
+  assert_equals: expected 60 but got 30
+[FAIL] Range 1-6 should not include the hyphen.
+  assert_equals: expected 50 but got 25
+[FAIL] Range 0-7 should include the hyphen.
+  assert_equals: expected 70 but got 33.34375
+[FAIL] Range 1-7 should include the hyphen.
+  assert_equals: expected 60 but got 28.34375
+[FAIL] Range 0-8 should include the hyphen.
+  assert_equals: expected 70 but got 33.34375
+[FAIL] Range 0-8 should include only the first hyphen.
+  assert_equals: expected 70 but got 33.34375
+[PASS] Collapsed soft-hyphen should be 0 width.
+[FAIL] Rendered soft-hyphen should have a width.
+  assert_equals: expected 10 but got 3.34375
+[PASS] Collapsed soft-hyphen in a span should be 0 width.
+[FAIL] Rendered soft-hyphen in a span should have a width.
+  assert_equals: expected 10 but got 3.34375
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom/caretPositionFromPoint-with-transformation-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom/caretPositionFromPoint-with-transformation-expected.txt
new file mode 100644
index 0000000..ed6d508
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom/caretPositionFromPoint-with-transformation-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught TypeError: frameDoc.caretPositionFromPoint is not a function
+[TIMEOUT] iframe's with equal content should report the same caret offset
+  Test timed out
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom/getComputedStyle-insets-relpos-inline-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom/getComputedStyle-insets-relpos-inline-expected.txt
new file mode 100644
index 0000000..86ed93a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/cssom/getComputedStyle-insets-relpos-inline-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+[FAIL] OOF with left fixed right auto in relpos inline container
+  assert_equals: expected "140px" but got "1.125px"
+[FAIL] OOF with left auto right fixed in relpos inline container
+  assert_equals: expected "140px" but got "1.125px"
+[FAIL] OOF with left fixed right auto in relpos inline container with mixed directions
+  assert_equals: expected "140px" but got "1.125px"
+[FAIL] OOF with left auto right fixed in relpos inline container with mixed directions
+  assert_equals: expected "140px" but got "1.125px"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/mediaqueries/test_media_queries-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/mediaqueries/test_media_queries-expected.txt
new file mode 100644
index 0000000..3f73390f1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/css/mediaqueries/test_media_queries-expected.txt
@@ -0,0 +1,1350 @@
+This is a testharness.js-based test.
+Found 1345 tests; 1343 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] query_should_be_parseable: (orientation)
+[PASS] query_should_be_parseable: not (orientation)
+[PASS] expression_should_be_known: (orientation)
+[PASS] expression_should_be_known: not (orientation)
+[PASS] query_should_not_be_parseable: only (orientation)
+[PASS] query_should_be_parseable: all and (orientation)
+[PASS] query_should_be_parseable: not all and (orientation)
+[PASS] query_should_be_parseable: only all and (orientation)
+[PASS] query_should_not_be_parseable: not not (orientation)
+[PASS] query_should_be_parseable: (orientation) and (orientation)
+[PASS] query_should_be_parseable: (orientation) or (orientation)
+[PASS] query_should_be_parseable: (orientation) or ((orientation) and ((orientation) or (orientation) or (not (orientation))))
+[PASS] expression_should_be_known: (orientation) and (orientation)
+[PASS] expression_should_be_known: (orientation) or (orientation)
+[PASS] expression_should_be_known: (orientation) or ((orientation) and ((orientation) or (orientation) or (not (orientation))))
+[PASS] query_should_not_be_parseable: all and (orientation) or (orientation)
+[PASS] query_should_be_parseable: all and (orientation) and (orientation)
+[PASS] query_should_not_be_parseable: (orientation) and (orientation) or (orientation)
+[PASS] query_should_not_be_parseable: (orientation) and not (orientation)
+[PASS] expression_should_be_known: width
+[PASS] expression_should_be_parseable: min-width
+[PASS] expression_should_be_unknown: min-width
+[PASS] expression_should_be_parseable: max-width
+[PASS] expression_should_be_unknown: max-width
+[PASS] expression_should_be_known: width : 0
+[PASS] expression_should_be_known: width : 0px
+[PASS] expression_should_be_known: width : 0em
+[PASS] expression_should_be_known: width : -0
+[PASS] expression_should_be_known: width : -0cm
+[PASS] expression_should_be_known: width : 1px
+[PASS] expression_should_be_known: width : 0.001mm
+[PASS] expression_should_be_known: width : 100000px
+[PASS] expression_should_be_known: min-width : -0
+[PASS] expression_should_be_known: max-width : -0
+[PASS] expression_should_be_known: width : -1px
+[PASS] expression_should_be_known: min-width : -1px
+[PASS] expression_should_be_known: max-width : -1px
+[PASS] expression_should_be_known: width : -0.00001mm
+[PASS] expression_should_be_known: width : -100000em
+[PASS] expression_should_be_parseable: 0px : width : 0px
+[PASS] expression_should_be_unknown: 0px : width : 0px
+[PASS] expression_should_be_parseable: 0px : width > 0px
+[PASS] expression_should_be_unknown: 0px : width > 0px
+[PASS] expression_should_be_parseable: 0px : width >= 0px
+[PASS] expression_should_be_unknown: 0px : width >= 0px
+[PASS] expression_should_be_parseable: 0px : width = 0px
+[PASS] expression_should_be_unknown: 0px : width = 0px
+[PASS] expression_should_be_parseable: 0px : width <= 0px
+[PASS] expression_should_be_unknown: 0px : width <= 0px
+[PASS] expression_should_be_parseable: 0px : width < 0px
+[PASS] expression_should_be_unknown: 0px : width < 0px
+[PASS] expression_should_be_known: width > 0
+[PASS] expression_should_be_known: width > 0px
+[PASS] expression_should_be_known: width > 0em
+[PASS] expression_should_be_known: width > -0
+[PASS] expression_should_be_known: width > -0cm
+[PASS] expression_should_be_known: width > 1px
+[PASS] expression_should_be_known: width > 0.001mm
+[PASS] expression_should_be_known: width > 100000px
+[PASS] expression_should_be_parseable: min-width > -0
+[PASS] expression_should_be_unknown: min-width > -0
+[PASS] expression_should_be_parseable: max-width > -0
+[PASS] expression_should_be_unknown: max-width > -0
+[PASS] expression_should_be_known: 0px > width > 100000px
+[PASS] expression_should_be_known: width > -1px
+[PASS] expression_should_be_parseable: min-width > -1px
+[PASS] expression_should_be_unknown: min-width > -1px
+[PASS] expression_should_be_parseable: max-width > -1px
+[PASS] expression_should_be_unknown: max-width > -1px
+[PASS] expression_should_be_known: width > -0.00001mm
+[PASS] expression_should_be_known: width > -100000em
+[PASS] expression_should_be_parseable: 0px > width : 0px
+[PASS] expression_should_be_unknown: 0px > width : 0px
+[PASS] expression_should_be_known: 0px > width > 0px
+[PASS] expression_should_be_known: 0px > width >= 0px
+[PASS] expression_should_be_parseable: 0px > width = 0px
+[PASS] expression_should_be_unknown: 0px > width = 0px
+[PASS] expression_should_be_parseable: 0px > width <= 0px
+[PASS] expression_should_be_unknown: 0px > width <= 0px
+[PASS] expression_should_be_parseable: 0px > width < 0px
+[PASS] expression_should_be_unknown: 0px > width < 0px
+[PASS] expression_should_be_known: width >= 0
+[PASS] expression_should_be_known: width >= 0px
+[PASS] expression_should_be_known: width >= 0em
+[PASS] expression_should_be_known: width >= -0
+[PASS] expression_should_be_known: width >= -0cm
+[PASS] expression_should_be_known: width >= 1px
+[PASS] expression_should_be_known: width >= 0.001mm
+[PASS] expression_should_be_known: width >= 100000px
+[PASS] expression_should_be_parseable: min-width >= -0
+[PASS] expression_should_be_unknown: min-width >= -0
+[PASS] expression_should_be_parseable: max-width >= -0
+[PASS] expression_should_be_unknown: max-width >= -0
+[PASS] expression_should_be_known: 0px >= width >= 100000px
+[PASS] expression_should_be_parseable: width > = 0px
+[PASS] expression_should_be_unknown: width > = 0px
+[PASS] expression_should_be_known: width >= -1px
+[PASS] expression_should_be_parseable: min-width >= -1px
+[PASS] expression_should_be_unknown: min-width >= -1px
+[PASS] expression_should_be_parseable: max-width >= -1px
+[PASS] expression_should_be_unknown: max-width >= -1px
+[PASS] expression_should_be_known: width >= -0.00001mm
+[PASS] expression_should_be_known: width >= -100000em
+[PASS] expression_should_be_parseable: 0px >= width : 0px
+[PASS] expression_should_be_unknown: 0px >= width : 0px
+[PASS] expression_should_be_known: 0px >= width > 0px
+[PASS] expression_should_be_known: 0px >= width >= 0px
+[PASS] expression_should_be_parseable: 0px >= width = 0px
+[PASS] expression_should_be_unknown: 0px >= width = 0px
+[PASS] expression_should_be_parseable: 0px >= width <= 0px
+[PASS] expression_should_be_unknown: 0px >= width <= 0px
+[PASS] expression_should_be_parseable: 0px >= width < 0px
+[PASS] expression_should_be_unknown: 0px >= width < 0px
+[PASS] expression_should_be_known: width = 0
+[PASS] expression_should_be_known: width = 0px
+[PASS] expression_should_be_known: width = 0em
+[PASS] expression_should_be_known: width = -0
+[PASS] expression_should_be_known: width = -0cm
+[PASS] expression_should_be_known: width = 1px
+[PASS] expression_should_be_known: width = 0.001mm
+[PASS] expression_should_be_known: width = 100000px
+[PASS] expression_should_be_parseable: min-width = -0
+[PASS] expression_should_be_unknown: min-width = -0
+[PASS] expression_should_be_parseable: max-width = -0
+[PASS] expression_should_be_unknown: max-width = -0
+[PASS] expression_should_be_parseable: 0px = width = 100000px
+[PASS] expression_should_be_unknown: 0px = width = 100000px
+[PASS] expression_should_be_known: width = -1px
+[PASS] expression_should_be_parseable: min-width = -1px
+[PASS] expression_should_be_unknown: min-width = -1px
+[PASS] expression_should_be_parseable: max-width = -1px
+[PASS] expression_should_be_unknown: max-width = -1px
+[PASS] expression_should_be_known: width = -0.00001mm
+[PASS] expression_should_be_known: width = -100000em
+[PASS] expression_should_be_parseable: 0px = width : 0px
+[PASS] expression_should_be_unknown: 0px = width : 0px
+[PASS] expression_should_be_parseable: 0px = width > 0px
+[PASS] expression_should_be_unknown: 0px = width > 0px
+[PASS] expression_should_be_parseable: 0px = width >= 0px
+[PASS] expression_should_be_unknown: 0px = width >= 0px
+[PASS] expression_should_be_parseable: 0px = width = 0px
+[PASS] expression_should_be_unknown: 0px = width = 0px
+[PASS] expression_should_be_parseable: 0px = width <= 0px
+[PASS] expression_should_be_unknown: 0px = width <= 0px
+[PASS] expression_should_be_parseable: 0px = width < 0px
+[PASS] expression_should_be_unknown: 0px = width < 0px
+[PASS] expression_should_be_known: width <= 0
+[PASS] expression_should_be_known: width <= 0px
+[PASS] expression_should_be_known: width <= 0em
+[PASS] expression_should_be_known: width <= -0
+[PASS] expression_should_be_known: width <= -0cm
+[PASS] expression_should_be_known: width <= 1px
+[PASS] expression_should_be_known: width <= 0.001mm
+[PASS] expression_should_be_known: width <= 100000px
+[PASS] expression_should_be_parseable: min-width <= -0
+[PASS] expression_should_be_unknown: min-width <= -0
+[PASS] expression_should_be_parseable: max-width <= -0
+[PASS] expression_should_be_unknown: max-width <= -0
+[PASS] expression_should_be_known: 0px <= width <= 100000px
+[PASS] expression_should_be_parseable: width < = 0px
+[PASS] expression_should_be_unknown: width < = 0px
+[PASS] expression_should_be_known: width <= -1px
+[PASS] expression_should_be_parseable: min-width <= -1px
+[PASS] expression_should_be_unknown: min-width <= -1px
+[PASS] expression_should_be_parseable: max-width <= -1px
+[PASS] expression_should_be_unknown: max-width <= -1px
+[PASS] expression_should_be_known: width <= -0.00001mm
+[PASS] expression_should_be_known: width <= -100000em
+[PASS] expression_should_be_parseable: 0px <= width : 0px
+[PASS] expression_should_be_unknown: 0px <= width : 0px
+[PASS] expression_should_be_parseable: 0px <= width > 0px
+[PASS] expression_should_be_unknown: 0px <= width > 0px
+[PASS] expression_should_be_parseable: 0px <= width >= 0px
+[PASS] expression_should_be_unknown: 0px <= width >= 0px
+[PASS] expression_should_be_parseable: 0px <= width = 0px
+[PASS] expression_should_be_unknown: 0px <= width = 0px
+[PASS] expression_should_be_known: 0px <= width <= 0px
+[PASS] expression_should_be_known: 0px <= width < 0px
+[PASS] expression_should_be_known: width < 0
+[PASS] expression_should_be_known: width < 0px
+[PASS] expression_should_be_known: width < 0em
+[PASS] expression_should_be_known: width < -0
+[PASS] expression_should_be_known: width < -0cm
+[PASS] expression_should_be_known: width < 1px
+[PASS] expression_should_be_known: width < 0.001mm
+[PASS] expression_should_be_known: width < 100000px
+[PASS] expression_should_be_parseable: min-width < -0
+[PASS] expression_should_be_unknown: min-width < -0
+[PASS] expression_should_be_parseable: max-width < -0
+[PASS] expression_should_be_unknown: max-width < -0
+[PASS] expression_should_be_known: 0px < width < 100000px
+[PASS] expression_should_be_known: width < -1px
+[PASS] expression_should_be_parseable: min-width < -1px
+[PASS] expression_should_be_unknown: min-width < -1px
+[PASS] expression_should_be_parseable: max-width < -1px
+[PASS] expression_should_be_unknown: max-width < -1px
+[PASS] expression_should_be_known: width < -0.00001mm
+[PASS] expression_should_be_known: width < -100000em
+[PASS] expression_should_be_parseable: 0px < width : 0px
+[PASS] expression_should_be_unknown: 0px < width : 0px
+[PASS] expression_should_be_parseable: 0px < width > 0px
+[PASS] expression_should_be_unknown: 0px < width > 0px
+[PASS] expression_should_be_parseable: 0px < width >= 0px
+[PASS] expression_should_be_unknown: 0px < width >= 0px
+[PASS] expression_should_be_parseable: 0px < width = 0px
+[PASS] expression_should_be_unknown: 0px < width = 0px
+[PASS] expression_should_be_known: 0px < width <= 0px
+[PASS] expression_should_be_known: 0px < width < 0px
+[PASS] expression_should_be_known: height
+[PASS] expression_should_be_parseable: min-height
+[PASS] expression_should_be_unknown: min-height
+[PASS] expression_should_be_parseable: max-height
+[PASS] expression_should_be_unknown: max-height
+[PASS] expression_should_be_known: height : 0
+[PASS] expression_should_be_known: height : 0px
+[PASS] expression_should_be_known: height : 0em
+[PASS] expression_should_be_known: height : -0
+[PASS] expression_should_be_known: height : -0cm
+[PASS] expression_should_be_known: height : 1px
+[PASS] expression_should_be_known: height : 0.001mm
+[PASS] expression_should_be_known: height : 100000px
+[PASS] expression_should_be_known: min-height : -0
+[PASS] expression_should_be_known: max-height : -0
+[PASS] expression_should_be_known: height : -1px
+[PASS] expression_should_be_known: min-height : -1px
+[PASS] expression_should_be_known: max-height : -1px
+[PASS] expression_should_be_known: height : -0.00001mm
+[PASS] expression_should_be_known: height : -100000em
+[PASS] expression_should_be_parseable: 0px : height : 0px
+[PASS] expression_should_be_unknown: 0px : height : 0px
+[PASS] expression_should_be_parseable: 0px : height > 0px
+[PASS] expression_should_be_unknown: 0px : height > 0px
+[PASS] expression_should_be_parseable: 0px : height >= 0px
+[PASS] expression_should_be_unknown: 0px : height >= 0px
+[PASS] expression_should_be_parseable: 0px : height = 0px
+[PASS] expression_should_be_unknown: 0px : height = 0px
+[PASS] expression_should_be_parseable: 0px : height <= 0px
+[PASS] expression_should_be_unknown: 0px : height <= 0px
+[PASS] expression_should_be_parseable: 0px : height < 0px
+[PASS] expression_should_be_unknown: 0px : height < 0px
+[PASS] expression_should_be_known: height > 0
+[PASS] expression_should_be_known: height > 0px
+[PASS] expression_should_be_known: height > 0em
+[PASS] expression_should_be_known: height > -0
+[PASS] expression_should_be_known: height > -0cm
+[PASS] expression_should_be_known: height > 1px
+[PASS] expression_should_be_known: height > 0.001mm
+[PASS] expression_should_be_known: height > 100000px
+[PASS] expression_should_be_parseable: min-height > -0
+[PASS] expression_should_be_unknown: min-height > -0
+[PASS] expression_should_be_parseable: max-height > -0
+[PASS] expression_should_be_unknown: max-height > -0
+[PASS] expression_should_be_known: 0px > height > 100000px
+[PASS] expression_should_be_known: height > -1px
+[PASS] expression_should_be_parseable: min-height > -1px
+[PASS] expression_should_be_unknown: min-height > -1px
+[PASS] expression_should_be_parseable: max-height > -1px
+[PASS] expression_should_be_unknown: max-height > -1px
+[PASS] expression_should_be_known: height > -0.00001mm
+[PASS] expression_should_be_known: height > -100000em
+[PASS] expression_should_be_parseable: 0px > height : 0px
+[PASS] expression_should_be_unknown: 0px > height : 0px
+[PASS] expression_should_be_known: 0px > height > 0px
+[PASS] expression_should_be_known: 0px > height >= 0px
+[PASS] expression_should_be_parseable: 0px > height = 0px
+[PASS] expression_should_be_unknown: 0px > height = 0px
+[PASS] expression_should_be_parseable: 0px > height <= 0px
+[PASS] expression_should_be_unknown: 0px > height <= 0px
+[PASS] expression_should_be_parseable: 0px > height < 0px
+[PASS] expression_should_be_unknown: 0px > height < 0px
+[PASS] expression_should_be_known: height >= 0
+[PASS] expression_should_be_known: height >= 0px
+[PASS] expression_should_be_known: height >= 0em
+[PASS] expression_should_be_known: height >= -0
+[PASS] expression_should_be_known: height >= -0cm
+[PASS] expression_should_be_known: height >= 1px
+[PASS] expression_should_be_known: height >= 0.001mm
+[PASS] expression_should_be_known: height >= 100000px
+[PASS] expression_should_be_parseable: min-height >= -0
+[PASS] expression_should_be_unknown: min-height >= -0
+[PASS] expression_should_be_parseable: max-height >= -0
+[PASS] expression_should_be_unknown: max-height >= -0
+[PASS] expression_should_be_known: 0px >= height >= 100000px
+[PASS] expression_should_be_parseable: height > = 0px
+[PASS] expression_should_be_unknown: height > = 0px
+[PASS] expression_should_be_known: height >= -1px
+[PASS] expression_should_be_parseable: min-height >= -1px
+[PASS] expression_should_be_unknown: min-height >= -1px
+[PASS] expression_should_be_parseable: max-height >= -1px
+[PASS] expression_should_be_unknown: max-height >= -1px
+[PASS] expression_should_be_known: height >= -0.00001mm
+[PASS] expression_should_be_known: height >= -100000em
+[PASS] expression_should_be_parseable: 0px >= height : 0px
+[PASS] expression_should_be_unknown: 0px >= height : 0px
+[PASS] expression_should_be_known: 0px >= height > 0px
+[PASS] expression_should_be_known: 0px >= height >= 0px
+[PASS] expression_should_be_parseable: 0px >= height = 0px
+[PASS] expression_should_be_unknown: 0px >= height = 0px
+[PASS] expression_should_be_parseable: 0px >= height <= 0px
+[PASS] expression_should_be_unknown: 0px >= height <= 0px
+[PASS] expression_should_be_parseable: 0px >= height < 0px
+[PASS] expression_should_be_unknown: 0px >= height < 0px
+[PASS] expression_should_be_known: height = 0
+[PASS] expression_should_be_known: height = 0px
+[PASS] expression_should_be_known: height = 0em
+[PASS] expression_should_be_known: height = -0
+[PASS] expression_should_be_known: height = -0cm
+[PASS] expression_should_be_known: height = 1px
+[PASS] expression_should_be_known: height = 0.001mm
+[PASS] expression_should_be_known: height = 100000px
+[PASS] expression_should_be_parseable: min-height = -0
+[PASS] expression_should_be_unknown: min-height = -0
+[PASS] expression_should_be_parseable: max-height = -0
+[PASS] expression_should_be_unknown: max-height = -0
+[PASS] expression_should_be_parseable: 0px = height = 100000px
+[PASS] expression_should_be_unknown: 0px = height = 100000px
+[PASS] expression_should_be_known: height = -1px
+[PASS] expression_should_be_parseable: min-height = -1px
+[PASS] expression_should_be_unknown: min-height = -1px
+[PASS] expression_should_be_parseable: max-height = -1px
+[PASS] expression_should_be_unknown: max-height = -1px
+[PASS] expression_should_be_known: height = -0.00001mm
+[PASS] expression_should_be_known: height = -100000em
+[PASS] expression_should_be_parseable: 0px = height : 0px
+[PASS] expression_should_be_unknown: 0px = height : 0px
+[PASS] expression_should_be_parseable: 0px = height > 0px
+[PASS] expression_should_be_unknown: 0px = height > 0px
+[PASS] expression_should_be_parseable: 0px = height >= 0px
+[PASS] expression_should_be_unknown: 0px = height >= 0px
+[PASS] expression_should_be_parseable: 0px = height = 0px
+[PASS] expression_should_be_unknown: 0px = height = 0px
+[PASS] expression_should_be_parseable: 0px = height <= 0px
+[PASS] expression_should_be_unknown: 0px = height <= 0px
+[PASS] expression_should_be_parseable: 0px = height < 0px
+[PASS] expression_should_be_unknown: 0px = height < 0px
+[PASS] expression_should_be_known: height <= 0
+[PASS] expression_should_be_known: height <= 0px
+[PASS] expression_should_be_known: height <= 0em
+[PASS] expression_should_be_known: height <= -0
+[PASS] expression_should_be_known: height <= -0cm
+[PASS] expression_should_be_known: height <= 1px
+[PASS] expression_should_be_known: height <= 0.001mm
+[PASS] expression_should_be_known: height <= 100000px
+[PASS] expression_should_be_parseable: min-height <= -0
+[PASS] expression_should_be_unknown: min-height <= -0
+[PASS] expression_should_be_parseable: max-height <= -0
+[PASS] expression_should_be_unknown: max-height <= -0
+[PASS] expression_should_be_known: 0px <= height <= 100000px
+[PASS] expression_should_be_parseable: height < = 0px
+[PASS] expression_should_be_unknown: height < = 0px
+[PASS] expression_should_be_known: height <= -1px
+[PASS] expression_should_be_parseable: min-height <= -1px
+[PASS] expression_should_be_unknown: min-height <= -1px
+[PASS] expression_should_be_parseable: max-height <= -1px
+[PASS] expression_should_be_unknown: max-height <= -1px
+[PASS] expression_should_be_known: height <= -0.00001mm
+[PASS] expression_should_be_known: height <= -100000em
+[PASS] expression_should_be_parseable: 0px <= height : 0px
+[PASS] expression_should_be_unknown: 0px <= height : 0px
+[PASS] expression_should_be_parseable: 0px <= height > 0px
+[PASS] expression_should_be_unknown: 0px <= height > 0px
+[PASS] expression_should_be_parseable: 0px <= height >= 0px
+[PASS] expression_should_be_unknown: 0px <= height >= 0px
+[PASS] expression_should_be_parseable: 0px <= height = 0px
+[PASS] expression_should_be_unknown: 0px <= height = 0px
+[PASS] expression_should_be_known: 0px <= height <= 0px
+[PASS] expression_should_be_known: 0px <= height < 0px
+[PASS] expression_should_be_known: height < 0
+[PASS] expression_should_be_known: height < 0px
+[PASS] expression_should_be_known: height < 0em
+[PASS] expression_should_be_known: height < -0
+[PASS] expression_should_be_known: height < -0cm
+[PASS] expression_should_be_known: height < 1px
+[PASS] expression_should_be_known: height < 0.001mm
+[PASS] expression_should_be_known: height < 100000px
+[PASS] expression_should_be_parseable: min-height < -0
+[PASS] expression_should_be_unknown: min-height < -0
+[PASS] expression_should_be_parseable: max-height < -0
+[PASS] expression_should_be_unknown: max-height < -0
+[PASS] expression_should_be_known: 0px < height < 100000px
+[PASS] expression_should_be_known: height < -1px
+[PASS] expression_should_be_parseable: min-height < -1px
+[PASS] expression_should_be_unknown: min-height < -1px
+[PASS] expression_should_be_parseable: max-height < -1px
+[PASS] expression_should_be_unknown: max-height < -1px
+[PASS] expression_should_be_known: height < -0.00001mm
+[PASS] expression_should_be_known: height < -100000em
+[PASS] expression_should_be_parseable: 0px < height : 0px
+[PASS] expression_should_be_unknown: 0px < height : 0px
+[PASS] expression_should_be_parseable: 0px < height > 0px
+[PASS] expression_should_be_unknown: 0px < height > 0px
+[PASS] expression_should_be_parseable: 0px < height >= 0px
+[PASS] expression_should_be_unknown: 0px < height >= 0px
+[PASS] expression_should_be_parseable: 0px < height = 0px
+[PASS] expression_should_be_unknown: 0px < height = 0px
+[PASS] expression_should_be_known: 0px < height <= 0px
+[PASS] expression_should_be_known: 0px < height < 0px
+[PASS] expression_should_be_known: device-width
+[PASS] expression_should_be_parseable: min-device-width
+[PASS] expression_should_be_unknown: min-device-width
+[PASS] expression_should_be_parseable: max-device-width
+[PASS] expression_should_be_unknown: max-device-width
+[PASS] expression_should_be_known: device-width : 0
+[PASS] expression_should_be_known: device-width : 0px
+[PASS] expression_should_be_known: device-width : 0em
+[PASS] expression_should_be_known: device-width : -0
+[PASS] expression_should_be_known: device-width : -0cm
+[PASS] expression_should_be_known: device-width : 1px
+[PASS] expression_should_be_known: device-width : 0.001mm
+[PASS] expression_should_be_known: device-width : 100000px
+[PASS] expression_should_be_known: min-device-width : -0
+[PASS] expression_should_be_known: max-device-width : -0
+[PASS] expression_should_be_known: device-width : -1px
+[PASS] expression_should_be_known: min-device-width : -1px
+[PASS] expression_should_be_known: max-device-width : -1px
+[PASS] expression_should_be_known: device-width : -0.00001mm
+[PASS] expression_should_be_known: device-width : -100000em
+[PASS] expression_should_be_parseable: 0px : device-width : 0px
+[PASS] expression_should_be_unknown: 0px : device-width : 0px
+[PASS] expression_should_be_parseable: 0px : device-width > 0px
+[PASS] expression_should_be_unknown: 0px : device-width > 0px
+[PASS] expression_should_be_parseable: 0px : device-width >= 0px
+[PASS] expression_should_be_unknown: 0px : device-width >= 0px
+[PASS] expression_should_be_parseable: 0px : device-width = 0px
+[PASS] expression_should_be_unknown: 0px : device-width = 0px
+[PASS] expression_should_be_parseable: 0px : device-width <= 0px
+[PASS] expression_should_be_unknown: 0px : device-width <= 0px
+[PASS] expression_should_be_parseable: 0px : device-width < 0px
+[PASS] expression_should_be_unknown: 0px : device-width < 0px
+[PASS] expression_should_be_known: device-width > 0
+[PASS] expression_should_be_known: device-width > 0px
+[PASS] expression_should_be_known: device-width > 0em
+[PASS] expression_should_be_known: device-width > -0
+[PASS] expression_should_be_known: device-width > -0cm
+[PASS] expression_should_be_known: device-width > 1px
+[PASS] expression_should_be_known: device-width > 0.001mm
+[PASS] expression_should_be_known: device-width > 100000px
+[PASS] expression_should_be_parseable: min-device-width > -0
+[PASS] expression_should_be_unknown: min-device-width > -0
+[PASS] expression_should_be_parseable: max-device-width > -0
+[PASS] expression_should_be_unknown: max-device-width > -0
+[PASS] expression_should_be_known: 0px > device-width > 100000px
+[PASS] expression_should_be_known: device-width > -1px
+[PASS] expression_should_be_parseable: min-device-width > -1px
+[PASS] expression_should_be_unknown: min-device-width > -1px
+[PASS] expression_should_be_parseable: max-device-width > -1px
+[PASS] expression_should_be_unknown: max-device-width > -1px
+[PASS] expression_should_be_known: device-width > -0.00001mm
+[PASS] expression_should_be_known: device-width > -100000em
+[PASS] expression_should_be_parseable: 0px > device-width : 0px
+[PASS] expression_should_be_unknown: 0px > device-width : 0px
+[PASS] expression_should_be_known: 0px > device-width > 0px
+[PASS] expression_should_be_known: 0px > device-width >= 0px
+[PASS] expression_should_be_parseable: 0px > device-width = 0px
+[PASS] expression_should_be_unknown: 0px > device-width = 0px
+[PASS] expression_should_be_parseable: 0px > device-width <= 0px
+[PASS] expression_should_be_unknown: 0px > device-width <= 0px
+[PASS] expression_should_be_parseable: 0px > device-width < 0px
+[PASS] expression_should_be_unknown: 0px > device-width < 0px
+[PASS] expression_should_be_known: device-width >= 0
+[PASS] expression_should_be_known: device-width >= 0px
+[PASS] expression_should_be_known: device-width >= 0em
+[PASS] expression_should_be_known: device-width >= -0
+[PASS] expression_should_be_known: device-width >= -0cm
+[PASS] expression_should_be_known: device-width >= 1px
+[PASS] expression_should_be_known: device-width >= 0.001mm
+[PASS] expression_should_be_known: device-width >= 100000px
+[PASS] expression_should_be_parseable: min-device-width >= -0
+[PASS] expression_should_be_unknown: min-device-width >= -0
+[PASS] expression_should_be_parseable: max-device-width >= -0
+[PASS] expression_should_be_unknown: max-device-width >= -0
+[PASS] expression_should_be_known: 0px >= device-width >= 100000px
+[PASS] expression_should_be_parseable: device-width > = 0px
+[PASS] expression_should_be_unknown: device-width > = 0px
+[PASS] expression_should_be_known: device-width >= -1px
+[PASS] expression_should_be_parseable: min-device-width >= -1px
+[PASS] expression_should_be_unknown: min-device-width >= -1px
+[PASS] expression_should_be_parseable: max-device-width >= -1px
+[PASS] expression_should_be_unknown: max-device-width >= -1px
+[PASS] expression_should_be_known: device-width >= -0.00001mm
+[PASS] expression_should_be_known: device-width >= -100000em
+[PASS] expression_should_be_parseable: 0px >= device-width : 0px
+[PASS] expression_should_be_unknown: 0px >= device-width : 0px
+[PASS] expression_should_be_known: 0px >= device-width > 0px
+[PASS] expression_should_be_known: 0px >= device-width >= 0px
+[PASS] expression_should_be_parseable: 0px >= device-width = 0px
+[PASS] expression_should_be_unknown: 0px >= device-width = 0px
+[PASS] expression_should_be_parseable: 0px >= device-width <= 0px
+[PASS] expression_should_be_unknown: 0px >= device-width <= 0px
+[PASS] expression_should_be_parseable: 0px >= device-width < 0px
+[PASS] expression_should_be_unknown: 0px >= device-width < 0px
+[PASS] expression_should_be_known: device-width = 0
+[PASS] expression_should_be_known: device-width = 0px
+[PASS] expression_should_be_known: device-width = 0em
+[PASS] expression_should_be_known: device-width = -0
+[PASS] expression_should_be_known: device-width = -0cm
+[PASS] expression_should_be_known: device-width = 1px
+[PASS] expression_should_be_known: device-width = 0.001mm
+[PASS] expression_should_be_known: device-width = 100000px
+[PASS] expression_should_be_parseable: min-device-width = -0
+[PASS] expression_should_be_unknown: min-device-width = -0
+[PASS] expression_should_be_parseable: max-device-width = -0
+[PASS] expression_should_be_unknown: max-device-width = -0
+[PASS] expression_should_be_parseable: 0px = device-width = 100000px
+[PASS] expression_should_be_unknown: 0px = device-width = 100000px
+[PASS] expression_should_be_known: device-width = -1px
+[PASS] expression_should_be_parseable: min-device-width = -1px
+[PASS] expression_should_be_unknown: min-device-width = -1px
+[PASS] expression_should_be_parseable: max-device-width = -1px
+[PASS] expression_should_be_unknown: max-device-width = -1px
+[PASS] expression_should_be_known: device-width = -0.00001mm
+[PASS] expression_should_be_known: device-width = -100000em
+[PASS] expression_should_be_parseable: 0px = device-width : 0px
+[PASS] expression_should_be_unknown: 0px = device-width : 0px
+[PASS] expression_should_be_parseable: 0px = device-width > 0px
+[PASS] expression_should_be_unknown: 0px = device-width > 0px
+[PASS] expression_should_be_parseable: 0px = device-width >= 0px
+[PASS] expression_should_be_unknown: 0px = device-width >= 0px
+[PASS] expression_should_be_parseable: 0px = device-width = 0px
+[PASS] expression_should_be_unknown: 0px = device-width = 0px
+[PASS] expression_should_be_parseable: 0px = device-width <= 0px
+[PASS] expression_should_be_unknown: 0px = device-width <= 0px
+[PASS] expression_should_be_parseable: 0px = device-width < 0px
+[PASS] expression_should_be_unknown: 0px = device-width < 0px
+[PASS] expression_should_be_known: device-width <= 0
+[PASS] expression_should_be_known: device-width <= 0px
+[PASS] expression_should_be_known: device-width <= 0em
+[PASS] expression_should_be_known: device-width <= -0
+[PASS] expression_should_be_known: device-width <= -0cm
+[PASS] expression_should_be_known: device-width <= 1px
+[PASS] expression_should_be_known: device-width <= 0.001mm
+[PASS] expression_should_be_known: device-width <= 100000px
+[PASS] expression_should_be_parseable: min-device-width <= -0
+[PASS] expression_should_be_unknown: min-device-width <= -0
+[PASS] expression_should_be_parseable: max-device-width <= -0
+[PASS] expression_should_be_unknown: max-device-width <= -0
+[PASS] expression_should_be_known: 0px <= device-width <= 100000px
+[PASS] expression_should_be_parseable: device-width < = 0px
+[PASS] expression_should_be_unknown: device-width < = 0px
+[PASS] expression_should_be_known: device-width <= -1px
+[PASS] expression_should_be_parseable: min-device-width <= -1px
+[PASS] expression_should_be_unknown: min-device-width <= -1px
+[PASS] expression_should_be_parseable: max-device-width <= -1px
+[PASS] expression_should_be_unknown: max-device-width <= -1px
+[PASS] expression_should_be_known: device-width <= -0.00001mm
+[PASS] expression_should_be_known: device-width <= -100000em
+[PASS] expression_should_be_parseable: 0px <= device-width : 0px
+[PASS] expression_should_be_unknown: 0px <= device-width : 0px
+[PASS] expression_should_be_parseable: 0px <= device-width > 0px
+[PASS] expression_should_be_unknown: 0px <= device-width > 0px
+[PASS] expression_should_be_parseable: 0px <= device-width >= 0px
+[PASS] expression_should_be_unknown: 0px <= device-width >= 0px
+[PASS] expression_should_be_parseable: 0px <= device-width = 0px
+[PASS] expression_should_be_unknown: 0px <= device-width = 0px
+[PASS] expression_should_be_known: 0px <= device-width <= 0px
+[PASS] expression_should_be_known: 0px <= device-width < 0px
+[PASS] expression_should_be_known: device-width < 0
+[PASS] expression_should_be_known: device-width < 0px
+[PASS] expression_should_be_known: device-width < 0em
+[PASS] expression_should_be_known: device-width < -0
+[PASS] expression_should_be_known: device-width < -0cm
+[PASS] expression_should_be_known: device-width < 1px
+[PASS] expression_should_be_known: device-width < 0.001mm
+[PASS] expression_should_be_known: device-width < 100000px
+[PASS] expression_should_be_parseable: min-device-width < -0
+[PASS] expression_should_be_unknown: min-device-width < -0
+[PASS] expression_should_be_parseable: max-device-width < -0
+[PASS] expression_should_be_unknown: max-device-width < -0
+[PASS] expression_should_be_known: 0px < device-width < 100000px
+[PASS] expression_should_be_known: device-width < -1px
+[PASS] expression_should_be_parseable: min-device-width < -1px
+[PASS] expression_should_be_unknown: min-device-width < -1px
+[PASS] expression_should_be_parseable: max-device-width < -1px
+[PASS] expression_should_be_unknown: max-device-width < -1px
+[PASS] expression_should_be_known: device-width < -0.00001mm
+[PASS] expression_should_be_known: device-width < -100000em
+[PASS] expression_should_be_parseable: 0px < device-width : 0px
+[PASS] expression_should_be_unknown: 0px < device-width : 0px
+[PASS] expression_should_be_parseable: 0px < device-width > 0px
+[PASS] expression_should_be_unknown: 0px < device-width > 0px
+[PASS] expression_should_be_parseable: 0px < device-width >= 0px
+[PASS] expression_should_be_unknown: 0px < device-width >= 0px
+[PASS] expression_should_be_parseable: 0px < device-width = 0px
+[PASS] expression_should_be_unknown: 0px < device-width = 0px
+[PASS] expression_should_be_known: 0px < device-width <= 0px
+[PASS] expression_should_be_known: 0px < device-width < 0px
+[PASS] expression_should_be_known: device-height
+[PASS] expression_should_be_parseable: min-device-height
+[PASS] expression_should_be_unknown: min-device-height
+[PASS] expression_should_be_parseable: max-device-height
+[PASS] expression_should_be_unknown: max-device-height
+[PASS] expression_should_be_known: device-height : 0
+[PASS] expression_should_be_known: device-height : 0px
+[PASS] expression_should_be_known: device-height : 0em
+[PASS] expression_should_be_known: device-height : -0
+[PASS] expression_should_be_known: device-height : -0cm
+[PASS] expression_should_be_known: device-height : 1px
+[PASS] expression_should_be_known: device-height : 0.001mm
+[PASS] expression_should_be_known: device-height : 100000px
+[PASS] expression_should_be_known: min-device-height : -0
+[PASS] expression_should_be_known: max-device-height : -0
+[PASS] expression_should_be_known: device-height : -1px
+[PASS] expression_should_be_known: min-device-height : -1px
+[PASS] expression_should_be_known: max-device-height : -1px
+[PASS] expression_should_be_known: device-height : -0.00001mm
+[PASS] expression_should_be_known: device-height : -100000em
+[PASS] expression_should_be_parseable: 0px : device-height : 0px
+[PASS] expression_should_be_unknown: 0px : device-height : 0px
+[PASS] expression_should_be_parseable: 0px : device-height > 0px
+[PASS] expression_should_be_unknown: 0px : device-height > 0px
+[PASS] expression_should_be_parseable: 0px : device-height >= 0px
+[PASS] expression_should_be_unknown: 0px : device-height >= 0px
+[PASS] expression_should_be_parseable: 0px : device-height = 0px
+[PASS] expression_should_be_unknown: 0px : device-height = 0px
+[PASS] expression_should_be_parseable: 0px : device-height <= 0px
+[PASS] expression_should_be_unknown: 0px : device-height <= 0px
+[PASS] expression_should_be_parseable: 0px : device-height < 0px
+[PASS] expression_should_be_unknown: 0px : device-height < 0px
+[PASS] expression_should_be_known: device-height > 0
+[PASS] expression_should_be_known: device-height > 0px
+[PASS] expression_should_be_known: device-height > 0em
+[PASS] expression_should_be_known: device-height > -0
+[PASS] expression_should_be_known: device-height > -0cm
+[PASS] expression_should_be_known: device-height > 1px
+[PASS] expression_should_be_known: device-height > 0.001mm
+[PASS] expression_should_be_known: device-height > 100000px
+[PASS] expression_should_be_parseable: min-device-height > -0
+[PASS] expression_should_be_unknown: min-device-height > -0
+[PASS] expression_should_be_parseable: max-device-height > -0
+[PASS] expression_should_be_unknown: max-device-height > -0
+[PASS] expression_should_be_known: 0px > device-height > 100000px
+[PASS] expression_should_be_known: device-height > -1px
+[PASS] expression_should_be_parseable: min-device-height > -1px
+[PASS] expression_should_be_unknown: min-device-height > -1px
+[PASS] expression_should_be_parseable: max-device-height > -1px
+[PASS] expression_should_be_unknown: max-device-height > -1px
+[PASS] expression_should_be_known: device-height > -0.00001mm
+[PASS] expression_should_be_known: device-height > -100000em
+[PASS] expression_should_be_parseable: 0px > device-height : 0px
+[PASS] expression_should_be_unknown: 0px > device-height : 0px
+[PASS] expression_should_be_known: 0px > device-height > 0px
+[PASS] expression_should_be_known: 0px > device-height >= 0px
+[PASS] expression_should_be_parseable: 0px > device-height = 0px
+[PASS] expression_should_be_unknown: 0px > device-height = 0px
+[PASS] expression_should_be_parseable: 0px > device-height <= 0px
+[PASS] expression_should_be_unknown: 0px > device-height <= 0px
+[PASS] expression_should_be_parseable: 0px > device-height < 0px
+[PASS] expression_should_be_unknown: 0px > device-height < 0px
+[PASS] expression_should_be_known: device-height >= 0
+[PASS] expression_should_be_known: device-height >= 0px
+[PASS] expression_should_be_known: device-height >= 0em
+[PASS] expression_should_be_known: device-height >= -0
+[PASS] expression_should_be_known: device-height >= -0cm
+[PASS] expression_should_be_known: device-height >= 1px
+[PASS] expression_should_be_known: device-height >= 0.001mm
+[PASS] expression_should_be_known: device-height >= 100000px
+[PASS] expression_should_be_parseable: min-device-height >= -0
+[PASS] expression_should_be_unknown: min-device-height >= -0
+[PASS] expression_should_be_parseable: max-device-height >= -0
+[PASS] expression_should_be_unknown: max-device-height >= -0
+[PASS] expression_should_be_known: 0px >= device-height >= 100000px
+[PASS] expression_should_be_parseable: device-height > = 0px
+[PASS] expression_should_be_unknown: device-height > = 0px
+[PASS] expression_should_be_known: device-height >= -1px
+[PASS] expression_should_be_parseable: min-device-height >= -1px
+[PASS] expression_should_be_unknown: min-device-height >= -1px
+[PASS] expression_should_be_parseable: max-device-height >= -1px
+[PASS] expression_should_be_unknown: max-device-height >= -1px
+[PASS] expression_should_be_known: device-height >= -0.00001mm
+[PASS] expression_should_be_known: device-height >= -100000em
+[PASS] expression_should_be_parseable: 0px >= device-height : 0px
+[PASS] expression_should_be_unknown: 0px >= device-height : 0px
+[PASS] expression_should_be_known: 0px >= device-height > 0px
+[PASS] expression_should_be_known: 0px >= device-height >= 0px
+[PASS] expression_should_be_parseable: 0px >= device-height = 0px
+[PASS] expression_should_be_unknown: 0px >= device-height = 0px
+[PASS] expression_should_be_parseable: 0px >= device-height <= 0px
+[PASS] expression_should_be_unknown: 0px >= device-height <= 0px
+[PASS] expression_should_be_parseable: 0px >= device-height < 0px
+[PASS] expression_should_be_unknown: 0px >= device-height < 0px
+[PASS] expression_should_be_known: device-height = 0
+[PASS] expression_should_be_known: device-height = 0px
+[PASS] expression_should_be_known: device-height = 0em
+[PASS] expression_should_be_known: device-height = -0
+[PASS] expression_should_be_known: device-height = -0cm
+[PASS] expression_should_be_known: device-height = 1px
+[PASS] expression_should_be_known: device-height = 0.001mm
+[PASS] expression_should_be_known: device-height = 100000px
+[PASS] expression_should_be_parseable: min-device-height = -0
+[PASS] expression_should_be_unknown: min-device-height = -0
+[PASS] expression_should_be_parseable: max-device-height = -0
+[PASS] expression_should_be_unknown: max-device-height = -0
+[PASS] expression_should_be_parseable: 0px = device-height = 100000px
+[PASS] expression_should_be_unknown: 0px = device-height = 100000px
+[PASS] expression_should_be_known: device-height = -1px
+[PASS] expression_should_be_parseable: min-device-height = -1px
+[PASS] expression_should_be_unknown: min-device-height = -1px
+[PASS] expression_should_be_parseable: max-device-height = -1px
+[PASS] expression_should_be_unknown: max-device-height = -1px
+[PASS] expression_should_be_known: device-height = -0.00001mm
+[PASS] expression_should_be_known: device-height = -100000em
+[PASS] expression_should_be_parseable: 0px = device-height : 0px
+[PASS] expression_should_be_unknown: 0px = device-height : 0px
+[PASS] expression_should_be_parseable: 0px = device-height > 0px
+[PASS] expression_should_be_unknown: 0px = device-height > 0px
+[PASS] expression_should_be_parseable: 0px = device-height >= 0px
+[PASS] expression_should_be_unknown: 0px = device-height >= 0px
+[PASS] expression_should_be_parseable: 0px = device-height = 0px
+[PASS] expression_should_be_unknown: 0px = device-height = 0px
+[PASS] expression_should_be_parseable: 0px = device-height <= 0px
+[PASS] expression_should_be_unknown: 0px = device-height <= 0px
+[PASS] expression_should_be_parseable: 0px = device-height < 0px
+[PASS] expression_should_be_unknown: 0px = device-height < 0px
+[PASS] expression_should_be_known: device-height <= 0
+[PASS] expression_should_be_known: device-height <= 0px
+[PASS] expression_should_be_known: device-height <= 0em
+[PASS] expression_should_be_known: device-height <= -0
+[PASS] expression_should_be_known: device-height <= -0cm
+[PASS] expression_should_be_known: device-height <= 1px
+[PASS] expression_should_be_known: device-height <= 0.001mm
+[PASS] expression_should_be_known: device-height <= 100000px
+[PASS] expression_should_be_parseable: min-device-height <= -0
+[PASS] expression_should_be_unknown: min-device-height <= -0
+[PASS] expression_should_be_parseable: max-device-height <= -0
+[PASS] expression_should_be_unknown: max-device-height <= -0
+[PASS] expression_should_be_known: 0px <= device-height <= 100000px
+[PASS] expression_should_be_parseable: device-height < = 0px
+[PASS] expression_should_be_unknown: device-height < = 0px
+[PASS] expression_should_be_known: device-height <= -1px
+[PASS] expression_should_be_parseable: min-device-height <= -1px
+[PASS] expression_should_be_unknown: min-device-height <= -1px
+[PASS] expression_should_be_parseable: max-device-height <= -1px
+[PASS] expression_should_be_unknown: max-device-height <= -1px
+[PASS] expression_should_be_known: device-height <= -0.00001mm
+[PASS] expression_should_be_known: device-height <= -100000em
+[PASS] expression_should_be_parseable: 0px <= device-height : 0px
+[PASS] expression_should_be_unknown: 0px <= device-height : 0px
+[PASS] expression_should_be_parseable: 0px <= device-height > 0px
+[PASS] expression_should_be_unknown: 0px <= device-height > 0px
+[PASS] expression_should_be_parseable: 0px <= device-height >= 0px
+[PASS] expression_should_be_unknown: 0px <= device-height >= 0px
+[PASS] expression_should_be_parseable: 0px <= device-height = 0px
+[PASS] expression_should_be_unknown: 0px <= device-height = 0px
+[PASS] expression_should_be_known: 0px <= device-height <= 0px
+[PASS] expression_should_be_known: 0px <= device-height < 0px
+[PASS] expression_should_be_known: device-height < 0
+[PASS] expression_should_be_known: device-height < 0px
+[PASS] expression_should_be_known: device-height < 0em
+[PASS] expression_should_be_known: device-height < -0
+[PASS] expression_should_be_known: device-height < -0cm
+[PASS] expression_should_be_known: device-height < 1px
+[PASS] expression_should_be_known: device-height < 0.001mm
+[PASS] expression_should_be_known: device-height < 100000px
+[PASS] expression_should_be_parseable: min-device-height < -0
+[PASS] expression_should_be_unknown: min-device-height < -0
+[PASS] expression_should_be_parseable: max-device-height < -0
+[PASS] expression_should_be_unknown: max-device-height < -0
+[PASS] expression_should_be_known: 0px < device-height < 100000px
+[PASS] expression_should_be_known: device-height < -1px
+[PASS] expression_should_be_parseable: min-device-height < -1px
+[PASS] expression_should_be_unknown: min-device-height < -1px
+[PASS] expression_should_be_parseable: max-device-height < -1px
+[PASS] expression_should_be_unknown: max-device-height < -1px
+[PASS] expression_should_be_known: device-height < -0.00001mm
+[PASS] expression_should_be_known: device-height < -100000em
+[PASS] expression_should_be_parseable: 0px < device-height : 0px
+[PASS] expression_should_be_unknown: 0px < device-height : 0px
+[PASS] expression_should_be_parseable: 0px < device-height > 0px
+[PASS] expression_should_be_unknown: 0px < device-height > 0px
+[PASS] expression_should_be_parseable: 0px < device-height >= 0px
+[PASS] expression_should_be_unknown: 0px < device-height >= 0px
+[PASS] expression_should_be_parseable: 0px < device-height = 0px
+[PASS] expression_should_be_unknown: 0px < device-height = 0px
+[PASS] expression_should_be_known: 0px < device-height <= 0px
+[PASS] expression_should_be_known: 0px < device-height < 0px
+[PASS] should_apply: all and (width: ${value}px)
+[PASS] should_apply: all and (width = ${value}px)
+[PASS] should_not_apply: all and (width: ${value + 1}px)
+[PASS] should_not_apply: all and (width: ${value - 1}px)
+[PASS] should_not_apply: all and (width = ${value + 1}px)
+[PASS] should_not_apply: all and (width = ${value - 1}px)
+[PASS] should_apply: all and (min-width: ${value}px)
+[PASS] should_not_apply: all and (min-width: ${value + 1}px)
+[PASS] should_apply: all and (min-width: ${value - 1}px)
+[PASS] should_apply: all and (max-width: ${value}px)
+[PASS] should_apply: all and (max-width: ${value + 1}px)
+[PASS] should_not_apply: all and (max-width: ${value - 1}px)
+[PASS] should_not_apply: all and (min-width: ${Math.ceil(value/em_size) + 1}em)
+[PASS] should_apply: all and (min-width: ${Math.floor(value/em_size) - 1}em)
+[PASS] should_apply: all and (max-width: ${Math.ceil(value/em_size) + 1}em)
+[PASS] should_not_apply: all and (max-width: ${Math.floor(value/em_size) - 1}em)
+[PASS] should_apply: (width <= ${value}px)
+[PASS] should_apply: (width >= ${value}px)
+[PASS] should_apply: (0px < width <= ${value}px)
+[PASS] should_apply: (${value}px >= width > 0px)
+[PASS] should_not_apply: (0px < width < ${value}px)
+[PASS] should_not_apply: (${value}px > width > 0px)
+[PASS] should_not_apply: (width < ${value}px)
+[PASS] should_not_apply: (width > ${value}px)
+[PASS] should_apply: (width < ${value + 1}px)
+[PASS] should_apply: (width <= ${value + 1}px)
+[PASS] should_not_apply: (width > ${value + 1}px)
+[PASS] should_not_apply: (width >= ${value + 1}px)
+[PASS] should_apply: (width > ${value - 1}px)
+[PASS] should_apply: (width >= ${value - 1}px)
+[PASS] should_not_apply: (width < ${value - 1}px)
+[PASS] should_not_apply: (width <= ${value - 1}px)
+[PASS] should_apply: (${value - 1}px < width)
+[PASS] should_apply: (${value - 1}px <= width)
+[PASS] should_not_apply: (${value - 1}px > width)
+[PASS] should_not_apply: (${value - 1}px >= width)
+[PASS] should_apply: (${value - 1}px < width < ${value + 1}px)
+[PASS] should_apply: (${value - 1}px < width <= ${value}px)
+[PASS] should_apply: (${value}px <= width < ${value + 1}px)
+[PASS] should_apply: (${value + 1}px > width > ${value - 1}px)
+[PASS] should_apply: (${value + 1}px > width >= ${value}px)
+[PASS] should_apply: (${value}px >= width > ${value - 1}px)
+[PASS] should_not_apply: (${value}px > width > ${value - 1}px)
+[PASS] should_not_apply: (${value + 1}px > width > ${value}px)
+[PASS] should_apply: all and (height: ${value}px)
+[PASS] should_apply: all and (height = ${value}px)
+[PASS] should_not_apply: all and (height: ${value + 1}px)
+[PASS] should_not_apply: all and (height: ${value - 1}px)
+[PASS] should_not_apply: all and (height = ${value + 1}px)
+[PASS] should_not_apply: all and (height = ${value - 1}px)
+[PASS] should_apply: all and (min-height: ${value}px)
+[PASS] should_not_apply: all and (min-height: ${value + 1}px)
+[PASS] should_apply: all and (min-height: ${value - 1}px)
+[PASS] should_apply: all and (max-height: ${value}px)
+[PASS] should_apply: all and (max-height: ${value + 1}px)
+[PASS] should_not_apply: all and (max-height: ${value - 1}px)
+[PASS] should_not_apply: all and (min-height: ${Math.ceil(value/em_size) + 1}em)
+[PASS] should_apply: all and (min-height: ${Math.floor(value/em_size) - 1}em)
+[PASS] should_apply: all and (max-height: ${Math.ceil(value/em_size) + 1}em)
+[PASS] should_not_apply: all and (max-height: ${Math.floor(value/em_size) - 1}em)
+[PASS] should_apply: (height <= ${value}px)
+[PASS] should_apply: (height >= ${value}px)
+[PASS] should_apply: (0px < height <= ${value}px)
+[PASS] should_apply: (${value}px >= height > 0px)
+[PASS] should_not_apply: (0px < height < ${value}px)
+[PASS] should_not_apply: (${value}px > height > 0px)
+[PASS] should_not_apply: (height < ${value}px)
+[PASS] should_not_apply: (height > ${value}px)
+[PASS] should_apply: (height < ${value + 1}px)
+[PASS] should_apply: (height <= ${value + 1}px)
+[PASS] should_not_apply: (height > ${value + 1}px)
+[PASS] should_not_apply: (height >= ${value + 1}px)
+[PASS] should_apply: (height > ${value - 1}px)
+[PASS] should_apply: (height >= ${value - 1}px)
+[PASS] should_not_apply: (height < ${value - 1}px)
+[PASS] should_not_apply: (height <= ${value - 1}px)
+[PASS] should_apply: (${value - 1}px < height)
+[PASS] should_apply: (${value - 1}px <= height)
+[PASS] should_not_apply: (${value - 1}px > height)
+[PASS] should_not_apply: (${value - 1}px >= height)
+[PASS] should_apply: (${value - 1}px < height < ${value + 1}px)
+[PASS] should_apply: (${value - 1}px < height <= ${value}px)
+[PASS] should_apply: (${value}px <= height < ${value + 1}px)
+[PASS] should_apply: (${value + 1}px > height > ${value - 1}px)
+[PASS] should_apply: (${value + 1}px > height >= ${value}px)
+[PASS] should_apply: (${value}px >= height > ${value - 1}px)
+[PASS] should_not_apply: (${value}px > height > ${value - 1}px)
+[PASS] should_not_apply: (${value + 1}px > height > ${value}px)
+[PASS] should_apply: all and (device-width: ${value}px)
+[PASS] should_apply: all and (device-width = ${value}px)
+[PASS] should_not_apply: all and (device-width: ${value + 1}px)
+[PASS] should_not_apply: all and (device-width: ${value - 1}px)
+[PASS] should_not_apply: all and (device-width = ${value + 1}px)
+[PASS] should_not_apply: all and (device-width = ${value - 1}px)
+[PASS] should_apply: all and (min-device-width: ${value}px)
+[PASS] should_not_apply: all and (min-device-width: ${value + 1}px)
+[PASS] should_apply: all and (min-device-width: ${value - 1}px)
+[PASS] should_apply: all and (max-device-width: ${value}px)
+[PASS] should_apply: all and (max-device-width: ${value + 1}px)
+[PASS] should_not_apply: all and (max-device-width: ${value - 1}px)
+[PASS] should_not_apply: all and (min-device-width: ${Math.ceil(value/em_size) + 1}em)
+[PASS] should_apply: all and (min-device-width: ${Math.floor(value/em_size) - 1}em)
+[PASS] should_apply: all and (max-device-width: ${Math.ceil(value/em_size) + 1}em)
+[PASS] should_not_apply: all and (max-device-width: ${Math.floor(value/em_size) - 1}em)
+[PASS] should_apply: (device-width <= ${value}px)
+[PASS] should_apply: (device-width >= ${value}px)
+[PASS] should_apply: (0px < device-width <= ${value}px)
+[PASS] should_apply: (${value}px >= device-width > 0px)
+[PASS] should_not_apply: (0px < device-width < ${value}px)
+[PASS] should_not_apply: (${value}px > device-width > 0px)
+[PASS] should_not_apply: (device-width < ${value}px)
+[PASS] should_not_apply: (device-width > ${value}px)
+[PASS] should_apply: (device-width < ${value + 1}px)
+[PASS] should_apply: (device-width <= ${value + 1}px)
+[PASS] should_not_apply: (device-width > ${value + 1}px)
+[PASS] should_not_apply: (device-width >= ${value + 1}px)
+[PASS] should_apply: (device-width > ${value - 1}px)
+[PASS] should_apply: (device-width >= ${value - 1}px)
+[PASS] should_not_apply: (device-width < ${value - 1}px)
+[PASS] should_not_apply: (device-width <= ${value - 1}px)
+[PASS] should_apply: (${value - 1}px < device-width)
+[PASS] should_apply: (${value - 1}px <= device-width)
+[PASS] should_not_apply: (${value - 1}px > device-width)
+[PASS] should_not_apply: (${value - 1}px >= device-width)
+[PASS] should_apply: (${value - 1}px < device-width < ${value + 1}px)
+[PASS] should_apply: (${value - 1}px < device-width <= ${value}px)
+[PASS] should_apply: (${value}px <= device-width < ${value + 1}px)
+[PASS] should_apply: (${value + 1}px > device-width > ${value - 1}px)
+[PASS] should_apply: (${value + 1}px > device-width >= ${value}px)
+[PASS] should_apply: (${value}px >= device-width > ${value - 1}px)
+[PASS] should_not_apply: (${value}px > device-width > ${value - 1}px)
+[PASS] should_not_apply: (${value + 1}px > device-width > ${value}px)
+[PASS] should_apply: all and (device-height: ${value}px)
+[PASS] should_apply: all and (device-height = ${value}px)
+[PASS] should_not_apply: all and (device-height: ${value + 1}px)
+[PASS] should_not_apply: all and (device-height: ${value - 1}px)
+[PASS] should_not_apply: all and (device-height = ${value + 1}px)
+[PASS] should_not_apply: all and (device-height = ${value - 1}px)
+[PASS] should_apply: all and (min-device-height: ${value}px)
+[PASS] should_not_apply: all and (min-device-height: ${value + 1}px)
+[PASS] should_apply: all and (min-device-height: ${value - 1}px)
+[PASS] should_apply: all and (max-device-height: ${value}px)
+[PASS] should_apply: all and (max-device-height: ${value + 1}px)
+[PASS] should_not_apply: all and (max-device-height: ${value - 1}px)
+[PASS] should_not_apply: all and (min-device-height: ${Math.ceil(value/em_size) + 1}em)
+[PASS] should_apply: all and (min-device-height: ${Math.floor(value/em_size) - 1}em)
+[PASS] should_apply: all and (max-device-height: ${Math.ceil(value/em_size) + 1}em)
+[PASS] should_not_apply: all and (max-device-height: ${Math.floor(value/em_size) - 1}em)
+[PASS] should_apply: (device-height <= ${value}px)
+[PASS] should_apply: (device-height >= ${value}px)
+[PASS] should_apply: (0px < device-height <= ${value}px)
+[PASS] should_apply: (${value}px >= device-height > 0px)
+[PASS] should_not_apply: (0px < device-height < ${value}px)
+[PASS] should_not_apply: (${value}px > device-height > 0px)
+[PASS] should_not_apply: (device-height < ${value}px)
+[PASS] should_not_apply: (device-height > ${value}px)
+[PASS] should_apply: (device-height < ${value + 1}px)
+[PASS] should_apply: (device-height <= ${value + 1}px)
+[PASS] should_not_apply: (device-height > ${value + 1}px)
+[PASS] should_not_apply: (device-height >= ${value + 1}px)
+[PASS] should_apply: (device-height > ${value - 1}px)
+[PASS] should_apply: (device-height >= ${value - 1}px)
+[PASS] should_not_apply: (device-height < ${value - 1}px)
+[PASS] should_not_apply: (device-height <= ${value - 1}px)
+[PASS] should_apply: (${value - 1}px < device-height)
+[PASS] should_apply: (${value - 1}px <= device-height)
+[PASS] should_not_apply: (${value - 1}px > device-height)
+[PASS] should_not_apply: (${value - 1}px >= device-height)
+[PASS] should_apply: (${value - 1}px < device-height < ${value + 1}px)
+[PASS] should_apply: (${value - 1}px < device-height <= ${value}px)
+[PASS] should_apply: (${value}px <= device-height < ${value + 1}px)
+[PASS] should_apply: (${value + 1}px > device-height > ${value - 1}px)
+[PASS] should_apply: (${value + 1}px > device-height >= ${value}px)
+[PASS] should_apply: (${value}px >= device-height > ${value - 1}px)
+[PASS] should_not_apply: (${value}px > device-height > ${value - 1}px)
+[PASS] should_not_apply: (${value + 1}px > device-height > ${value}px)
+[PASS] width = 0, height != 0: should_apply: all and (height)
+[PASS] width = 0, height != 0: should_not_apply: all and (width)
+[PASS] width = 0, height = 0: should_not_apply: all and (height)
+[PASS] width = 0, height = 0: should_not_apply: all and (width)
+[PASS] width = 0, height = 0: should_apply: all and (device-height)
+[PASS] width = 0, height = 0: should_apply: all and (device-width)
+[PASS] width != 0, height = 0: should_not_apply: all and (height)
+[PASS] width != 0, height = 0: should_apply: all and (width)
+[PASS] width != 0, height != 0: should_apply: all and (height)
+[PASS] width != 0, height != 0: should_apply: all and (width)
+[PASS] ratio that reduces to 59/40: expression_should_be_known: orientation
+[PASS] ratio that reduces to 59/40: expression_should_be_known: orientation: portrait
+[PASS] ratio that reduces to 59/40: expression_should_be_known: orientation: landscape
+[PASS] ratio that reduces to 59/40: expression_should_be_parseable: min-orientation
+[PASS] ratio that reduces to 59/40: expression_should_be_unknown: min-orientation
+[PASS] ratio that reduces to 59/40: expression_should_be_parseable: min-orientation: portrait
+[PASS] ratio that reduces to 59/40: expression_should_be_unknown: min-orientation: portrait
+[PASS] ratio that reduces to 59/40: expression_should_be_parseable: min-orientation: landscape
+[PASS] ratio that reduces to 59/40: expression_should_be_unknown: min-orientation: landscape
+[PASS] ratio that reduces to 59/40: expression_should_be_parseable: max-orientation
+[PASS] ratio that reduces to 59/40: expression_should_be_unknown: max-orientation
+[PASS] ratio that reduces to 59/40: expression_should_be_parseable: max-orientation: portrait
+[PASS] ratio that reduces to 59/40: expression_should_be_unknown: max-orientation: portrait
+[PASS] ratio that reduces to 59/40: expression_should_be_parseable: max-orientation: landscape
+[PASS] ratio that reduces to 59/40: expression_should_be_unknown: max-orientation: landscape
+[PASS] ratio that reduces to 59/40: should_apply: (orientation)
+[PASS] ratio that reduces to 59/40: should_apply: (orientation: landscape)
+[PASS] ratio that reduces to 59/40: should_not_apply: (orientation: portrait)
+[PASS] ratio that reduces to 59/40: should_apply: not all and (orientation: portrait)
+[PASS] ratio that reduces to 59/80: should_apply: (orientation)
+[PASS] ratio that reduces to 59/80: should_not_apply: (orientation: landscape)
+[PASS] ratio that reduces to 59/80: should_apply: not all and (orientation: landscape)
+[PASS] ratio that reduces to 59/80: should_apply: (orientation: portrait)
+[PASS] should_apply: (aspect-ratio: 59/80)
+[PASS] should_not_apply: (aspect-ratio: 58/80)
+[PASS] should_not_apply: (aspect-ratio: 59/81)
+[PASS] should_not_apply: (aspect-ratio: 60/80)
+[PASS] should_not_apply: (aspect-ratio: 59/79)
+[PASS] should_apply: (aspect-ratio: 177/240)
+[PASS] should_apply: (aspect-ratio: 413/560)
+[PASS] should_apply: (aspect-ratio: 5900/8000)
+[PASS] should_not_apply: (aspect-ratio: 5901/8000)
+[PASS] should_not_apply: (aspect-ratio: 5899/8000)
+[PASS] should_not_apply: (aspect-ratio: 5900/8001)
+[PASS] should_not_apply: (aspect-ratio: 5900/7999)
+[PASS] should_apply: (aspect-ratio)
+[PASS] should_apply: (min-aspect-ratio: 59/80)
+[PASS] should_apply: (min-aspect-ratio: 58/80)
+[PASS] should_apply: (min-aspect-ratio: 59/81)
+[PASS] should_not_apply: (min-aspect-ratio: 60/80)
+[PASS] should_not_apply: (min-aspect-ratio: 59/79)
+[PASS] expression_should_be_parseable: min-aspect-ratio
+[PASS] expression_should_be_unknown: min-aspect-ratio
+[PASS] should_apply: (max-aspect-ratio: 59/80)
+[PASS] should_not_apply: (max-aspect-ratio: 58/80)
+[PASS] should_not_apply: (max-aspect-ratio: 59/81)
+[PASS] should_apply: (max-aspect-ratio: 60/80)
+[PASS] should_apply: (max-aspect-ratio: 59/79)
+[PASS] expression_should_be_parseable: max-aspect-ratio
+[PASS] expression_should_be_unknown: max-aspect-ratio
+[PASS] should_apply: (device-aspect-ratio: ${real_dar})
+[PASS] should_apply: not all and (device-aspect-ratio: ${high_dar_1})
+[PASS] should_not_apply: all and (device-aspect-ratio: ${high_dar_2})
+[PASS] should_not_apply: all and (device-aspect-ratio: ${low_dar_1})
+[PASS] should_apply: not all and (device-aspect-ratio: ${low_dar_2})
+[PASS] should_apply: (device-aspect-ratio)
+[PASS] should_apply: (min-device-aspect-ratio: ${real_dar})
+[PASS] should_not_apply: all and (min-device-aspect-ratio: ${high_dar_1})
+[PASS] should_apply: not all and (min-device-aspect-ratio: ${high_dar_2})
+[PASS] should_not_apply: not all and (min-device-aspect-ratio: ${low_dar_1})
+[PASS] should_apply: all and (min-device-aspect-ratio: ${low_dar_2})
+[PASS] expression_should_be_parseable: min-device-aspect-ratio
+[PASS] expression_should_be_unknown: min-device-aspect-ratio
+[PASS] should_apply: all and (max-device-aspect-ratio: ${real_dar})
+[PASS] should_apply: (max-device-aspect-ratio: ${high_dar_1})
+[PASS] should_apply: (max-device-aspect-ratio: ${high_dar_2})
+[PASS] should_not_apply: all and (max-device-aspect-ratio: ${low_dar_1})
+[PASS] should_apply: not all and (max-device-aspect-ratio: ${low_dar_2})
+[PASS] expression_should_be_parseable: max-device-aspect-ratio
+[PASS] expression_should_be_unknown: max-device-aspect-ratio
+[PASS] expression_should_be_known: max-aspect-ratio: 1/1
+[PASS] expression_should_be_known: max-aspect-ratio: 1  /1
+[PASS] expression_should_be_known: max-aspect-ratio: 1  / 	\n1
+[PASS] expression_should_be_known: max-aspect-ratio: 1/\r1
+[PASS] expression_should_be_known: max-aspect-ratio: 1
+[PASS] expression_should_be_known: max-aspect-ratio: 0.5
+[PASS] expression_should_be_known: max-aspect-ratio: 1.0/1
+[PASS] expression_should_be_known: max-aspect-ratio: 1/1.0
+[PASS] expression_should_be_known: max-aspect-ratio: 1.0/1.0
+[PASS] expression_should_be_known: max-aspect-ratio: 0/1
+[PASS] expression_should_be_known: max-aspect-ratio: 1/0
+[PASS] expression_should_be_known: max-aspect-ratio: 0/0
+[PASS] expression_should_be_parseable: max-aspect-ratio: -1/1
+[PASS] expression_should_be_unknown: max-aspect-ratio: -1/1
+[PASS] expression_should_be_parseable: max-aspect-ratio: 1/-1
+[PASS] expression_should_be_unknown: max-aspect-ratio: 1/-1
+[PASS] expression_should_be_parseable: max-aspect-ratio: -1/-1
+[PASS] expression_should_be_unknown: max-aspect-ratio: -1/-1
+[PASS] expression_should_be_parseable: max-aspect-ratio: invalid
+[PASS] expression_should_be_unknown: max-aspect-ratio: invalid
+[PASS] expression_should_be_parseable: max-aspect-ratio: 1 / invalid
+[PASS] expression_should_be_unknown: max-aspect-ratio: 1 / invalid
+[PASS] expression_should_be_parseable: max-aspect-ratio: 1 invalid
+[PASS] expression_should_be_unknown: max-aspect-ratio: 1 invalid
+[PASS] expression_should_be_known: device-aspect-ratio: 1/1
+[PASS] expression_should_be_known: device-aspect-ratio: 1  /1
+[PASS] expression_should_be_known: device-aspect-ratio: 1  / 	\n1
+[PASS] expression_should_be_known: device-aspect-ratio: 1/\r1
+[PASS] expression_should_be_known: device-aspect-ratio: 1
+[PASS] expression_should_be_known: device-aspect-ratio: 0.5
+[PASS] expression_should_be_known: device-aspect-ratio: 1.0/1
+[PASS] expression_should_be_known: device-aspect-ratio: 1/1.0
+[PASS] expression_should_be_known: device-aspect-ratio: 1.0/1.0
+[PASS] expression_should_be_known: device-aspect-ratio: 0/1
+[PASS] expression_should_be_known: device-aspect-ratio: 1/0
+[PASS] expression_should_be_known: device-aspect-ratio: 0/0
+[PASS] expression_should_be_parseable: device-aspect-ratio: -1/1
+[PASS] expression_should_be_unknown: device-aspect-ratio: -1/1
+[PASS] expression_should_be_parseable: device-aspect-ratio: 1/-1
+[PASS] expression_should_be_unknown: device-aspect-ratio: 1/-1
+[PASS] expression_should_be_parseable: device-aspect-ratio: -1/-1
+[PASS] expression_should_be_unknown: device-aspect-ratio: -1/-1
+[PASS] expression_should_be_parseable: device-aspect-ratio: invalid
+[PASS] expression_should_be_unknown: device-aspect-ratio: invalid
+[PASS] expression_should_be_parseable: device-aspect-ratio: 1 / invalid
+[PASS] expression_should_be_unknown: device-aspect-ratio: 1 / invalid
+[PASS] expression_should_be_parseable: device-aspect-ratio: 1 invalid
+[PASS] expression_should_be_unknown: device-aspect-ratio: 1 invalid
+[PASS] monochrome_and_color
+[PASS] find_depth
+[PASS] should_apply: all and (color:8)
+[PASS] should_not_apply: all and (color:7)
+[PASS] should_not_apply: all and (color:9)
+[PASS] should_apply: all and (max-color:8)
+[PASS] should_not_apply: all and (max-color:7)
+[PASS] should_apply: all and (max-color:9)
+[PASS] should_apply: all and (color)
+[PASS] expression_should_be_parseable: max-color
+[PASS] expression_should_be_unknown: max-color
+[PASS] expression_should_be_parseable: min-color
+[PASS] expression_should_be_unknown: min-color
+[PASS] should_not_apply: all and (monochrome)
+[PASS] expression_should_be_parseable: max-monochrome
+[PASS] expression_should_be_unknown: max-monochrome
+[PASS] expression_should_be_parseable: min-monochrome
+[PASS] expression_should_be_unknown: min-monochrome
+[PASS] should_apply: not all and (monochrome)
+[PASS] should_not_apply: not all and (color)
+[PASS] should_apply: only all and (color)
+[PASS] should_not_apply: only all and (monochrome)
+[PASS] expression_should_be_known: color: 1
+[PASS] expression_should_be_known: color: 327
+[PASS] expression_should_be_known: color: 0
+[PASS] expression_should_be_parseable: color: 1.0
+[PASS] expression_should_be_unknown: color: 1.0
+[PASS] expression_should_be_known: color: -1
+[PASS] expression_should_be_parseable: color: 1/1
+[PASS] expression_should_be_unknown: color: 1/1
+[PASS] expression_should_be_known: min-monochrome: 1
+[PASS] expression_should_be_known: min-monochrome: 327
+[PASS] expression_should_be_known: min-monochrome: 0
+[PASS] expression_should_be_parseable: min-monochrome: 1.0
+[PASS] expression_should_be_unknown: min-monochrome: 1.0
+[PASS] expression_should_be_known: min-monochrome: -1
+[PASS] expression_should_be_parseable: min-monochrome: 1/1
+[PASS] expression_should_be_unknown: min-monochrome: 1/1
+[PASS] expression_should_be_known: max-color-index: 1
+[PASS] expression_should_be_known: max-color-index: 327
+[PASS] expression_should_be_known: max-color-index: 0
+[PASS] expression_should_be_parseable: max-color-index: 1.0
+[PASS] expression_should_be_unknown: max-color-index: 1.0
+[PASS] expression_should_be_known: max-color-index: -1
+[PASS] expression_should_be_parseable: max-color-index: 1/1
+[PASS] expression_should_be_unknown: max-color-index: 1/1
+[PASS] should_apply: (color-index: 0)
+[PASS] should_not_apply: (color-index: 1)
+[PASS] should_apply: (min-color-index: 0)
+[PASS] should_not_apply: (min-color-index: 1)
+[PASS] should_apply: (max-color-index: 0)
+[PASS] should_apply: (max-color-index: 1)
+[PASS] should_apply: (max-color-index: 157)
+[PASS] expression_should_be_known: resolution: 3dpi
+[PASS] expression_should_be_known: resolution:3dpi
+[PASS] expression_should_be_known: resolution: 3.0dpi
+[PASS] expression_should_be_known: resolution: 3.4dpi
+[PASS] expression_should_be_known: resolution	: 120dpcm
+[PASS] expression_should_be_known: resolution: 1dppx
+[PASS] expression_should_be_known: resolution: 1x
+[PASS] expression_should_be_known: resolution: 1.5dppx
+[PASS] expression_should_be_known: resolution: 1.5x
+[PASS] expression_should_be_known: resolution: 2.0dppx
+[PASS] expression_should_be_known: resolution: 0dpi
+[PASS] expression_should_be_known: resolution: 0dppx
+[PASS] expression_should_be_known: resolution: 0x
+[PASS] expression_should_be_known: resolution: calc(6x / 2)
+[PASS] expression_should_be_parseable: resolution: -3dpi
+[PASS] expression_should_be_unknown: resolution: -3dpi
+[PASS] expression_should_be_known: min-resolution: 3dpi
+[PASS] expression_should_be_known: min-resolution:3dpi
+[PASS] expression_should_be_known: min-resolution: 3.0dpi
+[PASS] expression_should_be_known: min-resolution: 3.4dpi
+[PASS] expression_should_be_known: min-resolution	: 120dpcm
+[PASS] expression_should_be_known: min-resolution: 1dppx
+[PASS] expression_should_be_known: min-resolution: 1x
+[PASS] expression_should_be_known: min-resolution: 1.5dppx
+[PASS] expression_should_be_known: min-resolution: 1.5x
+[PASS] expression_should_be_known: min-resolution: 2.0dppx
+[PASS] expression_should_be_known: min-resolution: 0dpi
+[PASS] expression_should_be_known: min-resolution: 0dppx
+[PASS] expression_should_be_known: min-resolution: 0x
+[PASS] expression_should_be_known: min-resolution: calc(6x / 2)
+[PASS] expression_should_be_parseable: min-resolution: -3dpi
+[PASS] expression_should_be_unknown: min-resolution: -3dpi
+[PASS] expression_should_be_known: max-resolution: 3dpi
+[PASS] expression_should_be_known: max-resolution:3dpi
+[PASS] expression_should_be_known: max-resolution: 3.0dpi
+[PASS] expression_should_be_known: max-resolution: 3.4dpi
+[PASS] expression_should_be_known: max-resolution	: 120dpcm
+[PASS] expression_should_be_known: max-resolution: 1dppx
+[PASS] expression_should_be_known: max-resolution: 1x
+[PASS] expression_should_be_known: max-resolution: 1.5dppx
+[PASS] expression_should_be_known: max-resolution: 1.5x
+[PASS] expression_should_be_known: max-resolution: 2.0dppx
+[PASS] expression_should_be_known: max-resolution: 0dpi
+[PASS] expression_should_be_known: max-resolution: 0dppx
+[PASS] expression_should_be_known: max-resolution: 0x
+[PASS] expression_should_be_known: max-resolution: calc(6x / 2)
+[PASS] expression_should_be_parseable: max-resolution: -3dpi
+[PASS] expression_should_be_unknown: max-resolution: -3dpi
+[PASS] find_resolution
+[PASS] resolution is exact: should_apply: (resolution: ${resolution}dpi)
+[PASS] resolution is exact: should_apply: (resolution: ${Math.floor(resolution/96)}dppx)
+[PASS] resolution is exact: should_apply: (resolution: ${Math.floor(resolution/96)}x)
+[PASS] resolution is exact: should_not_apply: (resolution: ${resolution + 1}dpi)
+[PASS] resolution is exact: should_not_apply: (resolution: ${resolution - 1}dpi)
+[PASS] should_apply: (min-resolution: ${dpi_low}dpi)
+[PASS] should_not_apply: not all and (min-resolution: ${dpi_low}dpi)
+[PASS] should_apply: not all and (min-resolution: ${dpi_high}dpi)
+[PASS] should_not_apply: all and (min-resolution: ${dpi_high}dpi)
+[PASS] should_apply: (min-resolution: ${dpcm_low}dpcm)
+[PASS] should_apply: (max-resolution: ${dpcm_high}dpcm)
+[PASS] should_not_apply: (max-resolution: ${dpcm_low}dpcm)
+[PASS] should_apply: not all and (min-resolution: ${dpcm_high}dpcm)
+[PASS] expression_should_be_known: scan
+[PASS] expression_should_be_known: scan: progressive
+[PASS] expression_should_be_known: scan:interlace
+[PASS] expression_should_be_parseable: min-scan:interlace
+[PASS] expression_should_be_unknown: min-scan:interlace
+[PASS] expression_should_be_parseable: scan: 1
+[PASS] expression_should_be_unknown: scan: 1
+[PASS] expression_should_be_parseable: max-scan
+[PASS] expression_should_be_unknown: max-scan
+[PASS] expression_should_be_parseable: max-scan: progressive
+[PASS] expression_should_be_unknown: max-scan: progressive
+[PASS] should_not_apply: (scan)
+[PASS] should_not_apply: (scan: progressive)
+[PASS] should_not_apply: (scan: interlace)
+[PASS] should_apply: not all and (scan)
+[PASS] should_apply: not all and (scan: progressive)
+[PASS] should_apply: not all and (scan: interlace)
+[PASS] expression_should_be_known: grid
+[PASS] expression_should_be_known: grid: 0
+[PASS] expression_should_be_known: grid: 1
+[PASS] expression_should_be_parseable: min-grid
+[PASS] expression_should_be_unknown: min-grid
+[PASS] expression_should_be_parseable: min-grid:0
+[PASS] expression_should_be_unknown: min-grid:0
+[PASS] expression_should_be_parseable: max-grid: 1
+[PASS] expression_should_be_unknown: max-grid: 1
+[PASS] expression_should_be_parseable: grid: 2
+[PASS] expression_should_be_unknown: grid: 2
+[PASS] expression_should_be_parseable: grid: -1
+[PASS] expression_should_be_unknown: grid: -1
+[PASS] should_not_apply: (grid)
+[PASS] should_apply: (grid: 0)
+[PASS] should_not_apply: (grid: 1)
+[PASS] should_not_apply: (grid: 2)
+[PASS] should_not_apply: (grid: -1)
+[PASS] should_apply: (orientation
+[PASS] should_not_apply: not all and (orientation
+[PASS] should_not_apply: (orientation:
+[PASS] should_not_apply: (orientation:)
+[PASS] should_not_apply: (orientation:  )
+[PASS] should_apply: all,(orientation:
+[PASS] should_not_apply: (orientation:,all
+[PASS] should_apply: not all and (grid
+[PASS] should_not_apply: only all and (grid
+[PASS] should_not_apply: (grid
+[PASS] should_apply: all,(grid
+[PASS] should_not_apply: (grid,all
+[PASS] should_apply: ,all
+[PASS] should_apply: all,
+[PASS] should_apply: ,all,
+[PASS] should_apply: all,badmedium
+[PASS] should_apply: badmedium,all
+[PASS] should_not_apply: ,badmedium,
+[PASS] should_apply: all,(badexpression)
+[PASS] should_apply: (badexpression),all
+[PASS] should_not_apply: (badexpression),badmedium
+[PASS] should_not_apply: badmedium,(badexpression)
+[PASS] should_apply: all,[badsyntax]
+[PASS] should_apply: [badsyntax],all
+[PASS] should_not_apply: badmedium,[badsyntax]
+[PASS] should_not_apply: [badsyntax],badmedium
+[PASS] query_should_not_be_parseable: all and color :
+[PASS] query_should_not_be_parseable: all and color : 1
+[PASS] should_not_apply: all and min-color : 1
+[PASS] should_not_apply: (bogus)
+[PASS] should_not_apply: not all and (bogus)
+[PASS] should_not_apply: only all and (bogus)
+[PASS] expression_should_be_known: overflow-block
+[PASS] expression_should_be_known: overflow-block: none
+[PASS] expression_should_be_known: overflow-block: paged
+[PASS] expression_should_be_known: overflow-block: scroll
+[PASS] expression_should_be_parseable: overflow-block: optional-paged
+[PASS] expression_should_be_unknown: overflow-block: optional-paged
+[PASS] expression_should_be_parseable: overflow-block: some-random-invalid-thing
+[PASS] expression_should_be_unknown: overflow-block: some-random-invalid-thing
+[PASS] Sanity check for overflow-block
+[PASS] expression_should_be_known: overflow-inline
+[PASS] expression_should_be_known: overflow-inline: none
+[PASS] expression_should_be_known: overflow-inline: scroll
+[PASS] expression_should_be_parseable: overflow-inline: some-random-invalid-thing
+[PASS] expression_should_be_unknown: overflow-inline: some-random-invalid-thing
+[PASS] Sanity check for overflow-inline
+[PASS] expression_should_be_known: update
+[PASS] expression_should_be_known: update: none
+[PASS] expression_should_be_known: update: slow
+[PASS] expression_should_be_known: update: fast
+[PASS] expression_should_be_parseable: update: some-random-invalid-thing
+[PASS] expression_should_be_unknown: update: some-random-invalid-thing
+[PASS] Sanity check for update
+[PASS] expression_should_be_known: hover
+[PASS] expression_should_be_known: hover: hover
+[PASS] expression_should_be_known: hover: none
+[PASS] expression_should_be_known: any-hover
+[PASS] expression_should_be_known: any-hover: hover
+[PASS] expression_should_be_known: any-hover: none
+[PASS] (hover) == (hover: hover)
+[PASS] (hover) == not (hover: none)
+[PASS] (any-hover) == (any-hover: hover)
+[PASS] (any-hover) == not (any-hover: none)
+[PASS] expression_should_be_known: pointer
+[PASS] expression_should_be_known: pointer: coarse
+[PASS] expression_should_be_known: pointer: fine
+[PASS] expression_should_be_known: pointer: none
+[PASS] expression_should_be_known: any-pointer
+[PASS] expression_should_be_known: any-pointer: coarse
+[PASS] expression_should_be_known: any-pointer: fine
+[PASS] expression_should_be_known: any-pointer: none
+[PASS] (pointer) == (pointer: coarse) or (pointer: fine)
+[PASS] (pointer) == not (pointer: none)
+[PASS] (any-pointer) == (any-pointer: coarse) or (any-pointer: fine)
+[PASS] (any-pointer) == not (any-pointer: none)
+[FAIL] 'or' keyword: should_not_apply: (height) or (height)
+  assert_true: expected true got false
+[PASS] 'or' keyword: should_apply: (width) or (height)
+[PASS] 'or' keyword: should_apply: (height) or (width)
+[PASS] 'or' keyword: should_apply: (height) or (width) or (height)
+[PASS] 'or' keyword: query_should_not_be_parseable: screen or (width)
+[PASS] 'or' keyword: query_should_not_be_parseable: screen and (width) or (height)
+[FAIL] nesting: should_not_apply: ((height))
+  assert_true: expected true got false
+[PASS] nesting: should_apply: ((width))
+[PASS] nesting: should_apply: (((((width)))))
+[PASS] nesting: should_apply: (((((width
+[PASS] 'not' keyword: should_not_apply: not (width)
+[PASS] 'not' keyword: should_apply: not (height)
+[PASS] 'not' keyword: should_apply: not ((width) and (height))
+[PASS] 'not' keyword: should_not_apply: not ((width) or (height))
+[PASS] 'not' keyword: should_not_apply: not ((width) and (not (height)))
+[PASS] 'not' keyword: query_should_not_be_parseable: not (width) and not (height)
+[PASS] 'not' keyword: query_should_not_be_parseable: not not (width)
+[PASS] 'not' keyword: query_should_be_parseable: not unknown(width) 
+[PASS] three-valued logic: should_not_apply: (unknown)
+[PASS] three-valued logic: should_not_apply: not (unknown)
+[PASS] three-valued logic: should_not_apply: ((unknown) and (width))
+[PASS] three-valued logic: should_not_apply: not ((unknown) and (width))
+[PASS] three-valued logic: should_not_apply: ((unknown) and (height))
+[PASS] three-valued logic: should_apply: not ((unknown) and (height))
+[PASS] three-valued logic: should_apply: ((unknown) or (width))
+[PASS] three-valued logic: should_not_apply: not ((unknown) or (width))
+[PASS] three-valued logic: should_not_apply: ((unknown) or (height))
+[PASS] three-valued logic: should_not_apply: not ((unknown) or (height))
+[PASS] three-valued logic: should_apply: (width) or (not ((unknown) and (width)))
+[PASS] three-valued logic: should_not_apply: (width) and (not ((unknown) and (width)))
+[PASS] three-valued logic: should_apply: (width) or (not ((unknown) or (width)))
+[PASS] three-valued logic: should_not_apply: (width) and (not ((unknown) or (width)))
+[PASS] three-valued logic: should_apply: (width) or (not ((unknown) and (height)))
+[PASS] three-valued logic: should_apply: (width) and (not ((unknown) and (height)))
+[PASS] three-valued logic: should_apply: (width) or (not ((unknown) or (height)))
+[PASS] three-valued logic: should_not_apply: (width) and (not ((unknown) or (height)))
+[PASS] three-valued logic: should_not_apply: unknown(width)
+[PASS] three-valued logic: should_not_apply: not unknown(width)
+[PASS] three-valued logic: should_apply: not (unknown(width) and (height))
+[PASS] three-valued logic: should_not_apply: not (unknown(width) or (height))
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/events/scrolling/overscroll-event-fired-to-scrolled-element-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/events/scrolling/overscroll-event-fired-to-scrolled-element-expected.txt
new file mode 100644
index 0000000..6516ebcc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/events/scrolling/overscroll-event-fired-to-scrolled-element-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Tests that the scrolled element gets overscroll event after fully scrolling by touch.
+  promise_test: Unhandled rejection with value: "error: Action action_sequence failed"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/events/scrolling/scrollend-event-fires-to-iframe-window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/events/scrolling/scrollend-event-fires-to-iframe-window-expected.txt
new file mode 100644
index 0000000..c127380
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/events/scrolling/scrollend-event-fires-to-iframe-window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = stale element reference: stale element not found\n  (Session info: chrome-headless-shell=121.0.6106.0)\nTraceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 596, in do_testharness\n    result = protocol.base.execute_script(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 56, in execute_script\n    return method(script)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 735, in execute_async_script\n    return self.send_session_command("POST", "execute/async", body)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 567, in send_command\n    raise err\nwebdriver.error.StaleElementReferenceException: stale element reference (404): stale element reference: stale element not found\n  (Session info: chrome-headless-shell=121.0.6106.0)\n\nRemote-end stacktrace:\n\n#0 0x563f4d1fd482 <unknown>\n#1 0x563f4d1eee03 <unknown>\n#2 0x563f4ceb37c9 <unknown>\n#3 0x563f4ceb7bea <unknown>\n#4 0x563f4ceb9066 <unknown>\n#5 0x563f4ceb9147 <unknown>\n#6 0x563f4ceb977b <unknown>\n#7 0x563f4ceb94e6 <unknown>\n#8 0x563f4cf281c8 <unknown>\n#9 0x563f4cf0fda2 <unknown>\n#10 0x563f4cee9c2f <unknown>\n#11 0x563f4cf27430 <unknown>\n#12 0x563f4cf0fa03 <unknown>\n#13 0x563f4cee8501 <unknown>\n#14 0x563f4cee7d14 <unknown>\n#15 0x563f4cee917c <unknown>\n#16 0x563f4d1a9a2a <unknown>\n#17 0x563f4d1c274c <unknown>\n#18 0x563f4d1c216b <unknown>\n#19 0x563f4d1c2bf5 <unknown>\n#20 0x563f4d1b316f <unknown>\n#21 0x563f4d1c30e9 <unknown>\n#22 0x563f4d19bbea <unknown>\n#23 0x563f4d1de9a8 <unknown>\n#24 0x563f4d1deb3a <unknown>\n#25 0x563f4d1ee0d6 <unknown>\n#26 0x7f1553294ac3 <unknown>\n#27 0x7f1553326a40 <unknown>\n\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/events/scrolling/scrollend-event-not-fired-on-no-scroll-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/events/scrolling/scrollend-event-not-fired-on-no-scroll-expected.txt
new file mode 100644
index 0000000..ad03ed0e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/events/scrolling/scrollend-event-not-fired-on-no-scroll-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection
+[PASS] No scroll via wheel on div shouldn't fire scrollend.
+[PASS] No scroll via keys on div shouldn't fire scrollend.
+[PASS] No scroll via wheel on document shouldn't fire scrollend.
+[PASS] No scroll via keys on document shouldn't fire scrollend.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/nodes/Document-createEvent.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/nodes/Document-createEvent.https-expected.txt
new file mode 100644
index 0000000..6dca3da0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/dom/nodes/Document-createEvent.https-expected.txt
@@ -0,0 +1,304 @@
+This is a testharness.js-based test.
+Found 273 tests; 257 PASS, 16 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] BeforeUnloadEvent should be an alias for BeforeUnloadEvent.
+[PASS] createEvent('BeforeUnloadEvent') should be initialized correctly.
+[PASS] beforeunloadevent should be an alias for BeforeUnloadEvent.
+[PASS] createEvent('beforeunloadevent') should be initialized correctly.
+[PASS] BEFOREUNLOADEVENT should be an alias for BeforeUnloadEvent.
+[PASS] createEvent('BEFOREUNLOADEVENT') should be initialized correctly.
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "BeforeUnloadEvents"
+[PASS] CompositionEvent should be an alias for CompositionEvent.
+[PASS] createEvent('CompositionEvent') should be initialized correctly.
+[PASS] compositionevent should be an alias for CompositionEvent.
+[PASS] createEvent('compositionevent') should be initialized correctly.
+[PASS] COMPOSITIONEVENT should be an alias for CompositionEvent.
+[PASS] createEvent('COMPOSITIONEVENT') should be initialized correctly.
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "CompositionEvents"
+[PASS] CustomEvent should be an alias for CustomEvent.
+[PASS] createEvent('CustomEvent') should be initialized correctly.
+[PASS] customevent should be an alias for CustomEvent.
+[PASS] createEvent('customevent') should be initialized correctly.
+[PASS] CUSTOMEVENT should be an alias for CustomEvent.
+[PASS] createEvent('CUSTOMEVENT') should be initialized correctly.
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "CustomEvents"
+[PASS] DeviceMotionEvent should be an alias for DeviceMotionEvent.
+[PASS] createEvent('DeviceMotionEvent') should be initialized correctly.
+[PASS] devicemotionevent should be an alias for DeviceMotionEvent.
+[PASS] createEvent('devicemotionevent') should be initialized correctly.
+[PASS] DEVICEMOTIONEVENT should be an alias for DeviceMotionEvent.
+[PASS] createEvent('DEVICEMOTIONEVENT') should be initialized correctly.
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "DeviceMotionEvents"
+[PASS] DeviceOrientationEvent should be an alias for DeviceOrientationEvent.
+[PASS] createEvent('DeviceOrientationEvent') should be initialized correctly.
+[PASS] deviceorientationevent should be an alias for DeviceOrientationEvent.
+[PASS] createEvent('deviceorientationevent') should be initialized correctly.
+[PASS] DEVICEORIENTATIONEVENT should be an alias for DeviceOrientationEvent.
+[PASS] createEvent('DEVICEORIENTATIONEVENT') should be initialized correctly.
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "DeviceOrientationEvents"
+[PASS] DragEvent should be an alias for DragEvent.
+[PASS] createEvent('DragEvent') should be initialized correctly.
+[PASS] dragevent should be an alias for DragEvent.
+[PASS] createEvent('dragevent') should be initialized correctly.
+[PASS] DRAGEVENT should be an alias for DragEvent.
+[PASS] createEvent('DRAGEVENT') should be initialized correctly.
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "DragEvents"
+[PASS] Event should be an alias for Event.
+[PASS] createEvent('Event') should be initialized correctly.
+[PASS] event should be an alias for Event.
+[PASS] createEvent('event') should be initialized correctly.
+[PASS] EVENT should be an alias for Event.
+[PASS] createEvent('EVENT') should be initialized correctly.
+[PASS] Events should be an alias for Event.
+[PASS] createEvent('Events') should be initialized correctly.
+[PASS] events should be an alias for Event.
+[PASS] createEvent('events') should be initialized correctly.
+[PASS] EVENTS should be an alias for Event.
+[PASS] createEvent('EVENTS') should be initialized correctly.
+[PASS] FocusEvent should be an alias for FocusEvent.
+[PASS] createEvent('FocusEvent') should be initialized correctly.
+[PASS] focusevent should be an alias for FocusEvent.
+[PASS] createEvent('focusevent') should be initialized correctly.
+[PASS] FOCUSEVENT should be an alias for FocusEvent.
+[PASS] createEvent('FOCUSEVENT') should be initialized correctly.
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "FocusEvents"
+[PASS] HashChangeEvent should be an alias for HashChangeEvent.
+[PASS] createEvent('HashChangeEvent') should be initialized correctly.
+[PASS] hashchangeevent should be an alias for HashChangeEvent.
+[PASS] createEvent('hashchangeevent') should be initialized correctly.
+[PASS] HASHCHANGEEVENT should be an alias for HashChangeEvent.
+[PASS] createEvent('HASHCHANGEEVENT') should be initialized correctly.
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "HashChangeEvents"
+[PASS] HTMLEvents should be an alias for Event.
+[PASS] createEvent('HTMLEvents') should be initialized correctly.
+[PASS] htmlevents should be an alias for Event.
+[PASS] createEvent('htmlevents') should be initialized correctly.
+[PASS] HTMLEVENTS should be an alias for Event.
+[PASS] createEvent('HTMLEVENTS') should be initialized correctly.
+[PASS] KeyboardEvent should be an alias for KeyboardEvent.
+[PASS] createEvent('KeyboardEvent') should be initialized correctly.
+[PASS] keyboardevent should be an alias for KeyboardEvent.
+[PASS] createEvent('keyboardevent') should be initialized correctly.
+[PASS] KEYBOARDEVENT should be an alias for KeyboardEvent.
+[PASS] createEvent('KEYBOARDEVENT') should be initialized correctly.
+[FAIL] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "KeyboardEvents"
+  assert_throws_dom: function "function () {\n          var evt = document.createEvent(plural);\n        }" did not throw
+[PASS] MessageEvent should be an alias for MessageEvent.
+[PASS] createEvent('MessageEvent') should be initialized correctly.
+[PASS] messageevent should be an alias for MessageEvent.
+[PASS] createEvent('messageevent') should be initialized correctly.
+[PASS] MESSAGEEVENT should be an alias for MessageEvent.
+[PASS] createEvent('MESSAGEEVENT') should be initialized correctly.
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "MessageEvents"
+[PASS] MouseEvent should be an alias for MouseEvent.
+[PASS] createEvent('MouseEvent') should be initialized correctly.
+[PASS] mouseevent should be an alias for MouseEvent.
+[PASS] createEvent('mouseevent') should be initialized correctly.
+[PASS] MOUSEEVENT should be an alias for MouseEvent.
+[PASS] createEvent('MOUSEEVENT') should be initialized correctly.
+[PASS] MouseEvents should be an alias for MouseEvent.
+[PASS] createEvent('MouseEvents') should be initialized correctly.
+[PASS] mouseevents should be an alias for MouseEvent.
+[PASS] createEvent('mouseevents') should be initialized correctly.
+[PASS] MOUSEEVENTS should be an alias for MouseEvent.
+[PASS] createEvent('MOUSEEVENTS') should be initialized correctly.
+[PASS] StorageEvent should be an alias for StorageEvent.
+[PASS] createEvent('StorageEvent') should be initialized correctly.
+[PASS] storageevent should be an alias for StorageEvent.
+[PASS] createEvent('storageevent') should be initialized correctly.
+[PASS] STORAGEEVENT should be an alias for StorageEvent.
+[PASS] createEvent('STORAGEEVENT') should be initialized correctly.
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "StorageEvents"
+[PASS] SVGEvents should be an alias for Event.
+[PASS] createEvent('SVGEvents') should be initialized correctly.
+[PASS] svgevents should be an alias for Event.
+[PASS] createEvent('svgevents') should be initialized correctly.
+[PASS] SVGEVENTS should be an alias for Event.
+[PASS] createEvent('SVGEVENTS') should be initialized correctly.
+[FAIL] TextEvent should be an alias for CompositionEvent.
+  assert_equals: expected object "[object CompositionEvent]" but got object "[object TextEvent]"
+[PASS] createEvent('TextEvent') should be initialized correctly.
+[FAIL] textevent should be an alias for CompositionEvent.
+  assert_equals: expected object "[object CompositionEvent]" but got object "[object TextEvent]"
+[PASS] createEvent('textevent') should be initialized correctly.
+[FAIL] TEXTEVENT should be an alias for CompositionEvent.
+  assert_equals: expected object "[object CompositionEvent]" but got object "[object TextEvent]"
+[PASS] createEvent('TEXTEVENT') should be initialized correctly.
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "TextEvents"
+[PASS] UIEvent should be an alias for UIEvent.
+[PASS] createEvent('UIEvent') should be initialized correctly.
+[PASS] uievent should be an alias for UIEvent.
+[PASS] createEvent('uievent') should be initialized correctly.
+[PASS] UIEVENT should be an alias for UIEvent.
+[PASS] createEvent('UIEVENT') should be initialized correctly.
+[PASS] UIEvents should be an alias for UIEvent.
+[PASS] createEvent('UIEvents') should be initialized correctly.
+[PASS] uievents should be an alias for UIEvent.
+[PASS] createEvent('uievents') should be initialized correctly.
+[PASS] UIEVENTS should be an alias for UIEvent.
+[PASS] createEvent('UIEVENTS') should be initialized correctly.
+[PRECONDITION_FAILED] TouchEvent should be an alias for TouchEvent.
+  'expose legacy touch event APIs'
+[PRECONDITION_FAILED] createEvent('TouchEvent') should be initialized correctly.
+  'expose legacy touch event APIs'
+[PRECONDITION_FAILED] touchevent should be an alias for TouchEvent.
+  'expose legacy touch event APIs'
+[PRECONDITION_FAILED] createEvent('touchevent') should be initialized correctly.
+  'expose legacy touch event APIs'
+[PRECONDITION_FAILED] TOUCHEVENT should be an alias for TouchEvent.
+  'expose legacy touch event APIs'
+[PRECONDITION_FAILED] createEvent('TOUCHEVENT') should be initialized correctly.
+  'expose legacy touch event APIs'
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "TouchEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for unrecognized arguments
+[FAIL] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "AnimationEvent"
+  assert_throws_dom: function "function () {\n      var evt = document.createEvent(eventInterface);\n    }" did not throw
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AnimationEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "AnimationPlaybackEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AnimationPlaybackEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "AnimationPlayerEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AnimationPlayerEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ApplicationCacheErrorEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ApplicationCacheErrorEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "AudioProcessingEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AudioProcessingEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "AutocompleteErrorEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "AutocompleteErrorEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "BeforeInstallPromptEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "BeforeInstallPromptEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "BlobEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "BlobEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ClipboardEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ClipboardEvents"
+[FAIL] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "CloseEvent"
+  assert_throws_dom: function "function () {\n      var evt = document.createEvent(eventInterface);\n    }" did not throw
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "CloseEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "CommandEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "CommandEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "DataContainerEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "DataContainerEvents"
+[FAIL] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ErrorEvent"
+  assert_throws_dom: function "function () {\n      var evt = document.createEvent(eventInterface);\n    }" did not throw
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ErrorEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ExtendableEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ExtendableEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ExtendableMessageEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ExtendableMessageEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "FetchEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "FetchEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "FontFaceSetLoadEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "FontFaceSetLoadEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "GamepadEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "GamepadEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "GeofencingEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "GeofencingEvents"
+[FAIL] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "IDBVersionChangeEvent"
+  assert_throws_dom: function "function () {\n      var evt = document.createEvent(eventInterface);\n    }" did not throw
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "IDBVersionChangeEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "InstallEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "InstallEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "KeyEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "KeyEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MIDIConnectionEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MIDIConnectionEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MIDIMessageEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MIDIMessageEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaEncryptedEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaEncryptedEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaKeyEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaKeyEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaKeyMessageEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaKeyMessageEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaQueryListEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaQueryListEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaStreamEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaStreamEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MediaStreamTrackEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MediaStreamTrackEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MouseScrollEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MouseScrollEvents"
+[FAIL] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "MutationEvent"
+  assert_throws_dom: function "function () {\n      var evt = document.createEvent(eventInterface);\n    }" did not throw
+[FAIL] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "MutationEvents"
+  assert_throws_dom: function "function () {\n        var evt = document.createEvent(eventInterface + "s");\n      }" did not throw
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "NotificationEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "NotificationEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "NotifyPaintEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "NotifyPaintEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "OfflineAudioCompletionEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "OfflineAudioCompletionEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "OrientationEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "OrientationEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PageTransition"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PageTransitions"
+[FAIL] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PageTransitionEvent"
+  assert_throws_dom: function "function () {\n      var evt = document.createEvent(eventInterface);\n    }" did not throw
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PageTransitionEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PointerEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PointerEvents"
+[FAIL] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PopStateEvent"
+  assert_throws_dom: function "function () {\n      var evt = document.createEvent(eventInterface);\n    }" did not throw
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PopStateEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PopUpEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PopUpEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PresentationConnectionAvailableEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PresentationConnectionAvailableEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PresentationConnectionCloseEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PresentationConnectionCloseEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ProgressEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ProgressEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PromiseRejectionEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PromiseRejectionEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "PushEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "PushEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "RTCDTMFToneChangeEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RTCDTMFToneChangeEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "RTCDataChannelEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RTCDataChannelEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "RTCIceCandidateEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RTCIceCandidateEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "RelatedEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "RelatedEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ResourceProgressEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ResourceProgressEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SVGEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SVGZoomEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SVGZoomEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ScrollAreaEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ScrollAreaEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SecurityPolicyViolationEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SecurityPolicyViolationEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ServicePortConnectEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ServicePortConnectEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "ServiceWorkerMessageEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "ServiceWorkerMessageEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SimpleGestureEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SimpleGestureEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SpeechRecognitionError"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SpeechRecognitionErrors"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SpeechRecognitionEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SpeechRecognitionEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SpeechSynthesisEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SpeechSynthesisEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SyncEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SyncEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "TimeEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TimeEvents"
+[FAIL] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "TrackEvent"
+  assert_throws_dom: function "function () {\n      var evt = document.createEvent(eventInterface);\n    }" did not throw
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TrackEvents"
+[FAIL] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "TransitionEvent"
+  assert_throws_dom: function "function () {\n      var evt = document.createEvent(eventInterface);\n    }" did not throw
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "TransitionEvents"
+[FAIL] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebGLContextEvent"
+  assert_throws_dom: function "function () {\n      var evt = document.createEvent(eventInterface);\n    }" did not throw
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebGLContextEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebKitAnimationEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebKitAnimationEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WebKitTransitionEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WebKitTransitionEvents"
+[FAIL] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "WheelEvent"
+  assert_throws_dom: function "function () {\n      var evt = document.createEvent(eventInterface);\n    }" did not throw
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "WheelEvents"
+[PASS] Should throw NOT_SUPPORTED_ERR for non-legacy event interface "XULCommandEvent"
+[PASS] Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "XULCommandEvents"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/edit-context/edit-context-execCommand.tentative.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/edit-context/edit-context-execCommand.tentative.https-expected.txt
new file mode 100644
index 0000000..beec6ed
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/edit-context/edit-context-execCommand.tentative.https-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] document.execCommand("inserttext") should not change the DOM or fire textupdate
+[PASS] document.execCommand("bold") should not change the DOM or fire textupdate
+[PASS] queryCommandState, queryCommandvalue, and queryCommandInterm should always return false
+[FAIL] document.execCommand("copy") should work but document.execCommand("cut") should not change the DOM or the clipboard
+  assert_true: 'copy' always returns true regardless of whether it did anything expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/edit-context/edit-context-inheritability.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/edit-context/edit-context-inheritability.tentative-expected.txt
new file mode 100644
index 0000000..1e8b8ce
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/edit-context/edit-context-inheritability.tentative-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+[PASS] Check that element with EditContext is editable and gets events
+[FAIL] Check that child of EditContext is editable and the parent EditContext gets the events
+  promise_test: Unhandled rejection with value: "error: Action send_keys failed"
+[PASS] Check that a contenteditable child of a contenteditable="false" is editable
+[PASS] Check that a contenteditable child of a contenteditable is editable, but the parent contenteditable gets the events
+[PASS] Check that an EditContext child of a contenteditable="false" parent is editable and gets events
+[FAIL] Check that an contenteditable child of an EditContext is editable, but the EditContext gets the events
+  promise_test: Unhandled rejection with value: "error: Action send_keys failed"
+[PASS] Check that an input element in an EditContext is the event target for beforeinput/input
+[FAIL] Check that for an EditContext child of an EditContext, the parent is the one that gets the events
+  promise_test: Unhandled rejection with value: "error: Action send_keys failed"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/edit-context/edit-context-input.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/edit-context/edit-context-input.tentative-expected.txt
new file mode 100644
index 0000000..efe1c51
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/edit-context/edit-context-input.tentative-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+[PASS] Testing EditContext English typing
+[PASS] EditContext should disable DOM mutation
+[FAIL] beforeInput(insertText) should be cancelable
+  promise_test: Unhandled rejection with value: "error: Action send_keys failed"
+[FAIL] EditContext should not receive events after being detached from element
+  promise_test: Unhandled rejection with value: "error: Action send_keys failed"
+[PASS] Backspace and delete in EditContext
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative-expected.txt
new file mode 100644
index 0000000..46e1f6f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative-expected.txt
@@ -0,0 +1,837 @@
+This is a testharness.js-based test.
+Found 780 tests; 726 PASS, 54 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] In <textarea>, execCommand("getHTML", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("getHTML", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): The command should be supported
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): <textarea>.value should be "ab[]c"
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("cut", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <textarea>, execCommand("cut", false, null), a[b]c): execCommand() should return true
+  assert_equals: expected true but got false
+[FAIL] In <textarea>, execCommand("cut", false, null), a[b]c): <textarea>.value should be "a[]c"
+  assert_equals: expected "a[]c" but got "a[b]c"
+[PASS] In <textarea>, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined
+[FAIL] In <textarea>, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut
+  assert_equals: expected (string) "deleteByCut" but got (undefined) undefined
+[FAIL] In <textarea>, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+  assert_equals: expected (object) Element node <textarea id="target"></textarea> but got (undefined) undefined
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): The command should be supported
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): The command should not be enabled
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): execCommand() should return false
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): <textarea>.value should be "abc[]d"
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): input.target should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): The command should be supported
+[FAIL] In <textarea>, execCommand("copy", false, null), a[bc]d): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <textarea>, execCommand("copy", false, null), a[bc]d): execCommand() should return true
+  assert_equals: expected true but got false
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): <textarea>.value should be "a[bc]d"
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): input.target should be undefined
+[FAIL] In <textarea>, execCommand("paste", false, null), a[]c): The command should be supported
+  assert_equals: expected true but got false
+[FAIL] In <textarea>, execCommand("paste", false, null), a[]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): The command should be supported
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): The command should be enabled
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): The command should be supported
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): <textarea>.value should be "[abc]"
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("undo", false, null), [a]bc): The command should be supported
+[FAIL] In <textarea>, execCommand("undo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("undo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("undo", false, null), [a]bc): <textarea>.value should be "[a]bc"
+[PASS] In <textarea>, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <textarea>, execCommand("undo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyUndo"
+[FAIL] In <textarea>, execCommand("undo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea>
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("redo", false, null), [a]bc): The command should be supported
+[FAIL] In <textarea>, execCommand("redo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("redo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("redo", false, null), [a]bc): <textarea>.value should be "[a]bc"
+[PASS] In <textarea>, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <textarea>, execCommand("redo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyRedo"
+[FAIL] In <textarea>, execCommand("redo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea>
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("redo", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <textarea>.value should be "ainserted[]c"
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined
+[FAIL] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText
+  assert_equals: expected "insertText" but got ""
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): <textarea>.value should be "a**inserted**[]c"
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): input.inputType should be insertText
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("removeformat", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("removeformat", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): <textarea>.value should be "a\n[]c"
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be insertParagraph
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): <textarea>.value should be "a\n[]c"
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be insertLineBreak
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("heading", false, h1), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("heading", false, h1), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <textarea> has focus
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <textarea> does not have focus
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> has focus
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> does not have focus
+[PASS] In <textarea>, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> has focus
+  assert_equals: expected "div" but got "p"
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> does not have focus
+  assert_equals: expected "div" but got "p"
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> has focus
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> does not have focus
+[PASS] In <textarea> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): <textarea>.value should be "ab[]c"
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): execCommand() should return true
+  assert_equals: expected true but got false
+[FAIL] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): <textarea>.value should be "a[]c"
+  assert_equals: expected "a[]c" but got "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined
+[FAIL] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut
+  assert_equals: expected (string) "deleteByCut" but got (undefined) undefined
+[FAIL] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+  assert_equals: expected (object) Element node <textarea id="target"></textarea> but got (undefined) undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): <textarea>.value should be "abc[]d"
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): execCommand() should return true
+  assert_equals: expected true but got false
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): <textarea>.value should be "a[bc]d"
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): input.target should be undefined
+[FAIL] In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): The command should be supported
+  assert_equals: expected true but got false
+[FAIL] In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): <textarea>.value should be "[abc]"
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): <textarea>.value should be "[a]bc"
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyUndo"
+[FAIL] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea>
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): <textarea>.value should be "[a]bc"
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyRedo"
+[FAIL] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea>
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <textarea>.value should be "ainserted[]c"
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined
+[FAIL] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText
+  assert_equals: expected "insertText" but got ""
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): <textarea>.value should be "a**inserted**[]c"
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): input.inputType should be insertText
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): <textarea>.value should be "a\n[]c"
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be insertParagraph
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): <textarea>.value should be "a\n[]c"
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be insertLineBreak
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <textarea> has focus
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <textarea> does not have focus
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> has focus
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> does not have focus
+[PASS] In <textarea> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> has focus
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> does not have focus
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> has focus
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> does not have focus
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=password-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=password-expected.txt
new file mode 100644
index 0000000..c123a669
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=password-expected.txt
@@ -0,0 +1,843 @@
+This is a testharness.js-based test.
+Found 780 tests; 720 PASS, 60 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] In <input type="password">, execCommand("getHTML", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="password">, execCommand("getHTML", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("bold", false, bold), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("bold", false, bold), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("bold", false, bold), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("bold", false, bold), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("bold", false, bold), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("italic", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("italic", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("italic", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("italic", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("italic", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("italic", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("underline", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("underline", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("underline", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("underline", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("underline", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("underline", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("strikethrough", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("strikethrough", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("superscript", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("superscript", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("superscript", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("superscript", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("superscript", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("cut", false, null), ab[]c): The command should be supported
+[PASS] In <input type="password">, execCommand("cut", false, null), ab[]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("cut", false, null), ab[]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("cut", false, null), ab[]c): <input>.value should be "ab[]c"
+[PASS] In <input type="password">, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("cut", false, null), ab[]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("cut", false, null), ab[]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("cut", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="password">, execCommand("cut", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <input type="password">, execCommand("cut", false, null), a[b]c): execCommand() should return true
+  assert_equals: expected true but got false
+[FAIL] In <input type="password">, execCommand("cut", false, null), a[b]c): <input>.value should be "a[]c"
+  assert_equals: expected "a[]c" but got "a[b]c"
+[PASS] In <input type="password">, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined
+[FAIL] In <input type="password">, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut
+  assert_equals: expected (string) "deleteByCut" but got (undefined) undefined
+[FAIL] In <input type="password">, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLInputElement]
+  assert_equals: expected (object) Element node <input id="target" type="password"></input> but got (undefined) undefined
+[PASS] In <input type="password">, execCommand("copy", false, null), abc[]d): The command should be supported
+[PASS] In <input type="password">, execCommand("copy", false, null), abc[]d): The command should not be enabled
+[PASS] In <input type="password">, execCommand("copy", false, null), abc[]d): execCommand() should return false
+[PASS] In <input type="password">, execCommand("copy", false, null), abc[]d): <input>.value should be "abc[]d"
+[PASS] In <input type="password">, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("copy", false, null), abc[]d): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("copy", false, null), abc[]d): input.target should be undefined
+[PASS] In <input type="password">, execCommand("copy", false, null), a[bc]d): The command should be supported
+[FAIL] In <input type="password">, execCommand("copy", false, null), a[bc]d): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <input type="password">, execCommand("copy", false, null), a[bc]d): execCommand() should return true
+  assert_equals: expected true but got false
+[PASS] In <input type="password">, execCommand("copy", false, null), a[bc]d): <input>.value should be "a[bc]d"
+[PASS] In <input type="password">, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("copy", false, null), a[bc]d): input.target should be undefined
+[FAIL] In <input type="password">, execCommand("paste", false, null), a[]c): The command should be supported
+  assert_equals: expected true but got false
+[FAIL] In <input type="password">, execCommand("paste", false, null), a[]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <input type="password">, execCommand("delete", false, null), ab[]c): The command should be supported
+[PASS] In <input type="password">, execCommand("delete", false, null), ab[]c): The command should be enabled
+[PASS] In <input type="password">, execCommand("delete", false, null), ab[]c): execCommand() should return true
+[PASS] In <input type="password">, execCommand("delete", false, null), ab[]c): <input>.value should be "a[]c"
+[PASS] In <input type="password">, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward
+[PASS] In <input type="password">, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password">, execCommand("delete", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("delete", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="password">, execCommand("delete", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="password">, execCommand("delete", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="password">, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward
+[PASS] In <input type="password">, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): The command should be supported
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): <input>.value should be "a[]c"
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward
+[PASS] In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password">, execCommand("selectall", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("selectall", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="password">, execCommand("selectall", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="password">, execCommand("selectall", false, null), a[b]c): <input>.value should be "[abc]"
+[PASS] In <input type="password">, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("selectall", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("undo", false, null), [a]bc): The command should be supported
+[FAIL] In <input type="password">, execCommand("undo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password">, execCommand("undo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password">, execCommand("undo", false, null), [a]bc): <input>.value should be "[a]bc"
+[PASS] In <input type="password">, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <input type="password">, execCommand("undo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyUndo"
+[FAIL] In <input type="password">, execCommand("undo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="password"></input>
+[PASS] In <input type="password">, execCommand("undo", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("undo", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="password">, execCommand("undo", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="password">, execCommand("undo", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo
+[PASS] In <input type="password">, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password">, execCommand("redo", false, null), [a]bc): The command should be supported
+[FAIL] In <input type="password">, execCommand("redo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password">, execCommand("redo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password">, execCommand("redo", false, null), [a]bc): <input>.value should be "[a]bc"
+[PASS] In <input type="password">, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <input type="password">, execCommand("redo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyRedo"
+[FAIL] In <input type="password">, execCommand("redo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="password"></input>
+[PASS] In <input type="password">, execCommand("redo", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="password">, execCommand("redo", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <input type="password">, execCommand("redo", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="password">, execCommand("redo", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="password">, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo
+[PASS] In <input type="password">, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password">, execCommand("indent", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("indent", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("indent", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("indent", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("indent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("indent", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("outdent", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("outdent", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("outdent", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("outdent", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("outdent", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("fontsize", false, 5), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("fontsize", false, 5), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="password">, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="password">, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled
+[PASS] In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true
+[PASS] In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <input>.value should be "ainserted[]c"
+[PASS] In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText
+[PASS] In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled
+[PASS] In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true
+[PASS] In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): <input>.value should be "a**inserted**[]c"
+[PASS] In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText
+[PASS] In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password">, execCommand("inserttext", false, ), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("inserttext", false, ), a[b]c): The command should be enabled
+[PASS] In <input type="password">, execCommand("inserttext", false, ), a[b]c): execCommand() should return true
+[PASS] In <input type="password">, execCommand("inserttext", false, ), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="password">, execCommand("inserttext", false, ), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("inserttext", false, ), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("inserttext", false, ), a[b]c): input.inputType should be insertText
+[PASS] In <input type="password">, execCommand("inserttext", false, ), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password">, execCommand("justifyleft", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("justifyleft", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("justifyright", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("justifyright", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("justifyright", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("justifyright", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("justifyright", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("justifycenter", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("justifycenter", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("justifyfull", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("justifyfull", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("removeformat", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="password">, execCommand("removeformat", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password">, execCommand("removeformat", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password">, execCommand("removeformat", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("removeformat", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("unlink", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("unlink", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("unlink", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("unlink", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("unlink", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("formatblock", false, div), a[b]c): The command should be supported
+[PASS] In <input type="password">, execCommand("formatblock", false, div), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("formatblock", false, div), a[b]c): execCommand() should return false
+[PASS] In <input type="password">, execCommand("formatblock", false, div), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("formatblock", false, div), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("heading", false, h1), a[b]c): The command should not be supported
+[PASS] In <input type="password">, execCommand("heading", false, h1), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported
+[FAIL] In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined
+[FAIL] In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <input> has focus
+  assert_equals: expected false but got true
+[FAIL] In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <input> does not have focus
+  assert_equals: expected false but got true
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported
+[FAIL] In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> has focus
+[PASS] In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> does not have focus
+[PASS] In <input type="password">, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported
+[PASS] In <input type="password">, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported
+[PASS] In <input type="password">, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported
+[FAIL] In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined
+[FAIL] In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> has focus
+  assert_equals: expected "div" but got "p"
+[FAIL] In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> does not have focus
+  assert_equals: expected "div" but got "p"
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported
+[FAIL] In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> has focus
+[PASS] In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> does not have focus
+[PASS] In <input type="password"> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): <input>.value should be "ab[]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): execCommand() should return true
+  assert_equals: expected true but got false
+[FAIL] In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): <input>.value should be "a[]c"
+  assert_equals: expected "a[]c" but got "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined
+[FAIL] In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut
+  assert_equals: expected (string) "deleteByCut" but got (undefined) undefined
+[FAIL] In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLInputElement]
+  assert_equals: expected (object) Element node <input id="target" type="password"></input> but got (undefined) undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): <input>.value should be "abc[]d"
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be supported
+[FAIL] In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): execCommand() should return true
+  assert_equals: expected true but got false
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): <input>.value should be "a[bc]d"
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): input.target should be undefined
+[FAIL] In <input type="password"> in contenteditable, execCommand("paste", false, null), a[]c): The command should be supported
+  assert_equals: expected true but got false
+[FAIL] In <input type="password"> in contenteditable, execCommand("paste", false, null), a[]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): <input>.value should be "a[]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward
+[PASS] In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): <input>.value should be "a[]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward
+[PASS] In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): <input>.value should be "[abc]"
+[PASS] In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): The command should be supported
+[FAIL] In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): <input>.value should be "[a]bc"
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyUndo"
+[FAIL] In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="password"></input>
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo
+[PASS] In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): The command should be supported
+[FAIL] In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): <input>.value should be "[a]bc"
+[PASS] In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyRedo"
+[FAIL] In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="password"></input>
+[PASS] In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo
+[PASS] In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <input>.value should be "ainserted[]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText
+[PASS] In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): <input>.value should be "a**inserted**[]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, ), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, ), a[b]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, ), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, ), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, ), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, ), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, ), a[b]c): input.inputType should be insertText
+[PASS] In <input type="password"> in contenteditable, execCommand("inserttext", false, ), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): execCommand() should return false
+[PASS] In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <input> has focus
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <input> does not have focus
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> has focus
+[PASS] In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> does not have focus
+[PASS] In <input type="password"> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> has focus
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> does not have focus
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be enabled
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return true
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> has focus
+[PASS] In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> does not have focus
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=text-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=text-expected.txt
new file mode 100644
index 0000000..574adf4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=text-expected.txt
@@ -0,0 +1,843 @@
+This is a testharness.js-based test.
+Found 780 tests; 720 PASS, 60 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] In <input type="text">, execCommand("getHTML", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="text">, execCommand("getHTML", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("bold", false, bold), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("bold", false, bold), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("bold", false, bold), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("bold", false, bold), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("bold", false, bold), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("italic", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("italic", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("italic", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("italic", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("italic", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("italic", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("underline", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("underline", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("underline", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("underline", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("underline", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("underline", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("strikethrough", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("strikethrough", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("superscript", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("superscript", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("superscript", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("superscript", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("superscript", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("cut", false, null), ab[]c): The command should be supported
+[PASS] In <input type="text">, execCommand("cut", false, null), ab[]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("cut", false, null), ab[]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("cut", false, null), ab[]c): <input>.value should be "ab[]c"
+[PASS] In <input type="text">, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("cut", false, null), ab[]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("cut", false, null), ab[]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("cut", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="text">, execCommand("cut", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <input type="text">, execCommand("cut", false, null), a[b]c): execCommand() should return true
+  assert_equals: expected true but got false
+[FAIL] In <input type="text">, execCommand("cut", false, null), a[b]c): <input>.value should be "a[]c"
+  assert_equals: expected "a[]c" but got "a[b]c"
+[PASS] In <input type="text">, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined
+[FAIL] In <input type="text">, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut
+  assert_equals: expected (string) "deleteByCut" but got (undefined) undefined
+[FAIL] In <input type="text">, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLInputElement]
+  assert_equals: expected (object) Element node <input id="target" type="text"></input> but got (undefined) undefined
+[PASS] In <input type="text">, execCommand("copy", false, null), abc[]d): The command should be supported
+[PASS] In <input type="text">, execCommand("copy", false, null), abc[]d): The command should not be enabled
+[PASS] In <input type="text">, execCommand("copy", false, null), abc[]d): execCommand() should return false
+[PASS] In <input type="text">, execCommand("copy", false, null), abc[]d): <input>.value should be "abc[]d"
+[PASS] In <input type="text">, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("copy", false, null), abc[]d): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("copy", false, null), abc[]d): input.target should be undefined
+[PASS] In <input type="text">, execCommand("copy", false, null), a[bc]d): The command should be supported
+[FAIL] In <input type="text">, execCommand("copy", false, null), a[bc]d): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <input type="text">, execCommand("copy", false, null), a[bc]d): execCommand() should return true
+  assert_equals: expected true but got false
+[PASS] In <input type="text">, execCommand("copy", false, null), a[bc]d): <input>.value should be "a[bc]d"
+[PASS] In <input type="text">, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("copy", false, null), a[bc]d): input.target should be undefined
+[FAIL] In <input type="text">, execCommand("paste", false, null), a[]c): The command should be supported
+  assert_equals: expected true but got false
+[FAIL] In <input type="text">, execCommand("paste", false, null), a[]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <input type="text">, execCommand("delete", false, null), ab[]c): The command should be supported
+[PASS] In <input type="text">, execCommand("delete", false, null), ab[]c): The command should be enabled
+[PASS] In <input type="text">, execCommand("delete", false, null), ab[]c): execCommand() should return true
+[PASS] In <input type="text">, execCommand("delete", false, null), ab[]c): <input>.value should be "a[]c"
+[PASS] In <input type="text">, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward
+[PASS] In <input type="text">, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text">, execCommand("delete", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("delete", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="text">, execCommand("delete", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="text">, execCommand("delete", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="text">, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward
+[PASS] In <input type="text">, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): The command should be supported
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): <input>.value should be "a[]c"
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward
+[PASS] In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text">, execCommand("selectall", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("selectall", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="text">, execCommand("selectall", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="text">, execCommand("selectall", false, null), a[b]c): <input>.value should be "[abc]"
+[PASS] In <input type="text">, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("selectall", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("undo", false, null), [a]bc): The command should be supported
+[FAIL] In <input type="text">, execCommand("undo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text">, execCommand("undo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text">, execCommand("undo", false, null), [a]bc): <input>.value should be "[a]bc"
+[PASS] In <input type="text">, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <input type="text">, execCommand("undo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyUndo"
+[FAIL] In <input type="text">, execCommand("undo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="text"></input>
+[PASS] In <input type="text">, execCommand("undo", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("undo", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="text">, execCommand("undo", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="text">, execCommand("undo", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo
+[PASS] In <input type="text">, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text">, execCommand("redo", false, null), [a]bc): The command should be supported
+[FAIL] In <input type="text">, execCommand("redo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text">, execCommand("redo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text">, execCommand("redo", false, null), [a]bc): <input>.value should be "[a]bc"
+[PASS] In <input type="text">, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <input type="text">, execCommand("redo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyRedo"
+[FAIL] In <input type="text">, execCommand("redo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="text"></input>
+[PASS] In <input type="text">, execCommand("redo", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="text">, execCommand("redo", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <input type="text">, execCommand("redo", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="text">, execCommand("redo", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="text">, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo
+[PASS] In <input type="text">, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text">, execCommand("indent", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("indent", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("indent", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("indent", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("indent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("indent", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("outdent", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("outdent", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("outdent", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("outdent", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("outdent", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("fontsize", false, 5), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("fontsize", false, 5), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="text">, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="text">, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled
+[PASS] In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true
+[PASS] In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <input>.value should be "ainserted[]c"
+[PASS] In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText
+[PASS] In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled
+[PASS] In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true
+[PASS] In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): <input>.value should be "a**inserted**[]c"
+[PASS] In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText
+[PASS] In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text">, execCommand("inserttext", false, ), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("inserttext", false, ), a[b]c): The command should be enabled
+[PASS] In <input type="text">, execCommand("inserttext", false, ), a[b]c): execCommand() should return true
+[PASS] In <input type="text">, execCommand("inserttext", false, ), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="text">, execCommand("inserttext", false, ), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("inserttext", false, ), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("inserttext", false, ), a[b]c): input.inputType should be insertText
+[PASS] In <input type="text">, execCommand("inserttext", false, ), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text">, execCommand("justifyleft", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("justifyleft", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("justifyright", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("justifyright", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("justifyright", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("justifyright", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("justifyright", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("justifycenter", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("justifycenter", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("justifyfull", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("justifyfull", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("removeformat", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="text">, execCommand("removeformat", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text">, execCommand("removeformat", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text">, execCommand("removeformat", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("removeformat", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("unlink", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("unlink", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("unlink", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("unlink", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("unlink", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("formatblock", false, div), a[b]c): The command should be supported
+[PASS] In <input type="text">, execCommand("formatblock", false, div), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("formatblock", false, div), a[b]c): execCommand() should return false
+[PASS] In <input type="text">, execCommand("formatblock", false, div), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("formatblock", false, div), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("heading", false, h1), a[b]c): The command should not be supported
+[PASS] In <input type="text">, execCommand("heading", false, h1), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported
+[FAIL] In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined
+[FAIL] In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <input> has focus
+  assert_equals: expected false but got true
+[FAIL] In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <input> does not have focus
+  assert_equals: expected false but got true
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported
+[FAIL] In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> has focus
+[PASS] In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> does not have focus
+[PASS] In <input type="text">, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported
+[PASS] In <input type="text">, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported
+[PASS] In <input type="text">, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported
+[FAIL] In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined
+[FAIL] In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> has focus
+  assert_equals: expected "div" but got "p"
+[FAIL] In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> does not have focus
+  assert_equals: expected "div" but got "p"
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported
+[FAIL] In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> has focus
+[PASS] In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> does not have focus
+[PASS] In <input type="text"> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): <input>.value should be "ab[]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): execCommand() should return true
+  assert_equals: expected true but got false
+[FAIL] In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): <input>.value should be "a[]c"
+  assert_equals: expected "a[]c" but got "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined
+[FAIL] In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut
+  assert_equals: expected (string) "deleteByCut" but got (undefined) undefined
+[FAIL] In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLInputElement]
+  assert_equals: expected (object) Element node <input id="target" type="text"></input> but got (undefined) undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): <input>.value should be "abc[]d"
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be supported
+[FAIL] In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): execCommand() should return true
+  assert_equals: expected true but got false
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): <input>.value should be "a[bc]d"
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): input.target should be undefined
+[FAIL] In <input type="text"> in contenteditable, execCommand("paste", false, null), a[]c): The command should be supported
+  assert_equals: expected true but got false
+[FAIL] In <input type="text"> in contenteditable, execCommand("paste", false, null), a[]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): <input>.value should be "a[]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward
+[PASS] In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): <input>.value should be "a[]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward
+[PASS] In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): <input>.value should be "[abc]"
+[PASS] In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): The command should be supported
+[FAIL] In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): <input>.value should be "[a]bc"
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyUndo"
+[FAIL] In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="text"></input>
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo
+[PASS] In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): The command should be supported
+[FAIL] In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): <input>.value should be "[a]bc"
+[PASS] In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyRedo"
+[FAIL] In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="text"></input>
+[PASS] In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo
+[PASS] In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <input>.value should be "ainserted[]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText
+[PASS] In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): <input>.value should be "a**inserted**[]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, ), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, ), a[b]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, ), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, ), a[b]c): <input>.value should be "a[]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, ), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, ), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, ), a[b]c): input.inputType should be insertText
+[PASS] In <input type="text"> in contenteditable, execCommand("inserttext", false, ), a[b]c): input.target should be [object HTMLInputElement]
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported
+[FAIL] In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): execCommand() should return false
+[PASS] In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <input> has focus
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <input> does not have focus
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> has focus
+[PASS] In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> does not have focus
+[PASS] In <input type="text"> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> has focus
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> does not have focus
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be enabled
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return true
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): <input>.value should be "a[b]c"
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> has focus
+[PASS] In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> does not have focus
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=textarea-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=textarea-expected.txt
new file mode 100644
index 0000000..46e1f6f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=textarea-expected.txt
@@ -0,0 +1,837 @@
+This is a testharness.js-based test.
+Found 780 tests; 726 PASS, 54 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] In <textarea>, execCommand("getHTML", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("getHTML", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("bold", false, bold), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("italic", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("underline", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("superscript", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): The command should be supported
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): <textarea>.value should be "ab[]c"
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), ab[]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("cut", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <textarea>, execCommand("cut", false, null), a[b]c): execCommand() should return true
+  assert_equals: expected true but got false
+[FAIL] In <textarea>, execCommand("cut", false, null), a[b]c): <textarea>.value should be "a[]c"
+  assert_equals: expected "a[]c" but got "a[b]c"
+[PASS] In <textarea>, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined
+[FAIL] In <textarea>, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut
+  assert_equals: expected (string) "deleteByCut" but got (undefined) undefined
+[FAIL] In <textarea>, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+  assert_equals: expected (object) Element node <textarea id="target"></textarea> but got (undefined) undefined
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): The command should be supported
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): The command should not be enabled
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): execCommand() should return false
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): <textarea>.value should be "abc[]d"
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), abc[]d): input.target should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): The command should be supported
+[FAIL] In <textarea>, execCommand("copy", false, null), a[bc]d): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <textarea>, execCommand("copy", false, null), a[bc]d): execCommand() should return true
+  assert_equals: expected true but got false
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): <textarea>.value should be "a[bc]d"
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("copy", false, null), a[bc]d): input.target should be undefined
+[FAIL] In <textarea>, execCommand("paste", false, null), a[]c): The command should be supported
+  assert_equals: expected true but got false
+[FAIL] In <textarea>, execCommand("paste", false, null), a[]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): The command should be supported
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): The command should be enabled
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward
+[PASS] In <textarea>, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward
+[PASS] In <textarea>, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): The command should be supported
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward
+[PASS] In <textarea>, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): <textarea>.value should be "[abc]"
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("selectall", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("undo", false, null), [a]bc): The command should be supported
+[FAIL] In <textarea>, execCommand("undo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("undo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("undo", false, null), [a]bc): <textarea>.value should be "[a]bc"
+[PASS] In <textarea>, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <textarea>, execCommand("undo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyUndo"
+[FAIL] In <textarea>, execCommand("undo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea>
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo
+[PASS] In <textarea>, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("redo", false, null), [a]bc): The command should be supported
+[FAIL] In <textarea>, execCommand("redo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("redo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("redo", false, null), [a]bc): <textarea>.value should be "[a]bc"
+[PASS] In <textarea>, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <textarea>, execCommand("redo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyRedo"
+[FAIL] In <textarea>, execCommand("redo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea>
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("redo", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo
+[PASS] In <textarea>, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("indent", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("outdent", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <textarea>.value should be "ainserted[]c"
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined
+[FAIL] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText
+  assert_equals: expected "insertText" but got ""
+[PASS] In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): <textarea>.value should be "a**inserted**[]c"
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText
+[PASS] In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): input.inputType should be insertText
+[PASS] In <textarea>, execCommand("inserttext", false, ), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyright", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("removeformat", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("removeformat", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("removeformat", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("unlink", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): <textarea>.value should be "a\n[]c"
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be insertParagraph
+[PASS] In <textarea>, execCommand("insertparagraph", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): <textarea>.value should be "a\n[]c"
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be insertLineBreak
+[PASS] In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): The command should be supported
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): execCommand() should return false
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("formatblock", false, div), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("heading", false, h1), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("heading", false, h1), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <textarea> has focus
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <textarea> does not have focus
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> has focus
+[PASS] In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> does not have focus
+[PASS] In <textarea>, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported
+[PASS] In <textarea>, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> has focus
+  assert_equals: expected "div" but got "p"
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> does not have focus
+  assert_equals: expected "div" but got "p"
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> has focus
+[PASS] In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> does not have focus
+[PASS] In <textarea> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): <textarea>.value should be "ab[]c"
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): execCommand() should return true
+  assert_equals: expected true but got false
+[FAIL] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): <textarea>.value should be "a[]c"
+  assert_equals: expected "a[]c" but got "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined
+[FAIL] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut
+  assert_equals: expected (string) "deleteByCut" but got (undefined) undefined
+[FAIL] In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+  assert_equals: expected (object) Element node <textarea id="target"></textarea> but got (undefined) undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): <textarea>.value should be "abc[]d"
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be enabled
+  assert_equals: expected true but got false
+[FAIL] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): execCommand() should return true
+  assert_equals: expected true but got false
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): <textarea>.value should be "a[bc]d"
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): input.target should be undefined
+[FAIL] In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): The command should be supported
+  assert_equals: expected true but got false
+[FAIL] In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward
+[PASS] In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward
+[PASS] In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): <textarea>.value should be "[abc]"
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): <textarea>.value should be "[a]bc"
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyUndo"
+[FAIL] In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea>
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo
+[PASS] In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): <textarea>.value should be "[a]bc"
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined
+[FAIL] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): input.inputType should be undefined
+  assert_equals: expected (undefined) undefined but got (string) "historyRedo"
+[FAIL] In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): input.target should be undefined
+  assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea>
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be enabled
+  assert_equals: expected true but got false
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo
+[PASS] In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <textarea>.value should be "ainserted[]c"
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined
+[FAIL] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText
+  assert_equals: expected "insertText" but got ""
+[PASS] In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): <textarea>.value should be "a**inserted**[]c"
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): <textarea>.value should be "a[]c"
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): input.inputType should be insertText
+[PASS] In <textarea> in contenteditable, execCommand("inserttext", false, ), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should be supported
+[FAIL] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should not be enabled
+  assert_equals: expected false but got true
+[FAIL] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): execCommand() should return false
+  assert_equals: expected false but got true
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): <textarea>.value should be "a\n[]c"
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be insertParagraph
+[PASS] In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): <textarea>.value should be "a\n[]c"
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be insertLineBreak
+[PASS] In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.target should be [object HTMLTextAreaElement]
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): execCommand() should return false
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <textarea> has focus
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <textarea> does not have focus
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> has focus
+[PASS] In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> does not have focus
+[PASS] In <textarea> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported
+[PASS] In <textarea> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> has focus
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> does not have focus
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be enabled
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return true
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): <textarea>.value should be "a[b]c"
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> has focus
+[PASS] In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> does not have focus
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-without-editable-element.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-without-editable-element.tentative-expected.txt
new file mode 100644
index 0000000..5fcca83
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/exec-command-without-editable-element.tentative-expected.txt
@@ -0,0 +1,459 @@
+This is a testharness.js-based test.
+Found 424 tests; 392 PASS, 32 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] ChildDocument.execCommand(bold, false, bold) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(bold, false, bold) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(bold, false, bold) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(bold, false, bold) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(bold, false, bold) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(italic, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(italic, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(italic, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(italic, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(italic, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(underline, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(underline, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(underline, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(underline, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(underline, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(strikethrough, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(strikethrough, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(strikethrough, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(strikethrough, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(strikethrough, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(subscript, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(subscript, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(subscript, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(subscript, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(subscript, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(superscript, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(superscript, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(superscript, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(superscript, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(superscript, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(cut, false, null) with ab[]c: calling execCommand
+[PASS] ChildDocument.execCommand(cut, false, null) with ab[]c: checking event on focused document
+[FAIL] ChildDocument.execCommand(cut, false, null) with ab[]c: checking event on executed document
+  assert_equals: "cut" event should be fired expected true but got false
+[PASS] ChildDocument.execCommand(cut, false, null) with ab[]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(cut, false, null) with ab[]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(cut, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(cut, false, null) with a[b]c: checking event on focused document
+[FAIL] ChildDocument.execCommand(cut, false, null) with a[b]c: checking event on executed document
+  assert_equals: "cut" event should be fired expected true but got false
+[PASS] ChildDocument.execCommand(cut, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(cut, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(copy, false, null) with ab[]c: calling execCommand
+[PASS] ChildDocument.execCommand(copy, false, null) with ab[]c: checking event on focused document
+[FAIL] ChildDocument.execCommand(copy, false, null) with ab[]c: checking event on executed document
+  assert_equals: "copy" event should be fired expected true but got false
+[PASS] ChildDocument.execCommand(copy, false, null) with ab[]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(copy, false, null) with ab[]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(copy, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(copy, false, null) with a[b]c: checking event on focused document
+[FAIL] ChildDocument.execCommand(copy, false, null) with a[b]c: checking event on executed document
+  assert_equals: "copy" event should be fired expected true but got false
+[PASS] ChildDocument.execCommand(copy, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(copy, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(delete, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(delete, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(delete, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(delete, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(delete, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(forwarddelete, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(forwarddelete, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(forwarddelete, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(forwarddelete, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(forwarddelete, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(selectall, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(selectall, false, null) with a[b]c: checking unexpected synchronous event
+[PASS] ChildDocument.execCommand(selectall, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(selectall, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(selectall, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(undo, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(undo, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(undo, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(undo, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(undo, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(redo, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(redo, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(redo, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(redo, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(redo, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(indent, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(indent, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(indent, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(indent, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(indent, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(outdent, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(outdent, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(outdent, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(outdent, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(outdent, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(backcolor, false, #000000) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(backcolor, false, #000000) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(backcolor, false, #000000) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(backcolor, false, #000000) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(backcolor, false, #000000) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(forecolor, false, #F0F0F0) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(forecolor, false, #F0F0F0) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(forecolor, false, #F0F0F0) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(forecolor, false, #F0F0F0) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(forecolor, false, #F0F0F0) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(hilitecolor, false, #FFFF00) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(hilitecolor, false, #FFFF00) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(hilitecolor, false, #FFFF00) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(hilitecolor, false, #FFFF00) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(hilitecolor, false, #FFFF00) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(fontname, false, DummyFont) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(fontname, false, DummyFont) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(fontname, false, DummyFont) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(fontname, false, DummyFont) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(fontname, false, DummyFont) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(fontsize, false, 5) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(fontsize, false, 5) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(fontsize, false, 5) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(fontsize, false, 5) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(fontsize, false, 5) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(inserthorizontalrule, false, null) with a[]bc: calling execCommand
+[PASS] ChildDocument.execCommand(inserthorizontalrule, false, null) with a[]bc: checking event on focused document
+[PASS] ChildDocument.execCommand(inserthorizontalrule, false, null) with a[]bc: checking event on executed document
+[PASS] ChildDocument.execCommand(inserthorizontalrule, false, null) with a[]bc: checking result content in focused document
+[PASS] ChildDocument.execCommand(inserthorizontalrule, false, null) with a[]bc: checking result content in executed document
+[PASS] ChildDocument.execCommand(createlink, false, foo.html) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(createlink, false, foo.html) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(createlink, false, foo.html) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(createlink, false, foo.html) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(createlink, false, foo.html) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(insertimage, false, no-image.png) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(insertimage, false, no-image.png) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(insertimage, false, no-image.png) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(insertimage, false, no-image.png) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(insertimage, false, no-image.png) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(inserthtml, false, <b>inserted</b>) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(inserthtml, false, <b>inserted</b>) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(inserthtml, false, <b>inserted</b>) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(inserthtml, false, <b>inserted</b>) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(inserthtml, false, <b>inserted</b>) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(inserttext, false, **inserted**) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(inserttext, false, **inserted**) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(inserttext, false, **inserted**) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(inserttext, false, **inserted**) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(inserttext, false, **inserted**) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(justifyleft, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(justifyleft, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(justifyleft, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(justifyleft, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(justifyleft, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(justifyright, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(justifyright, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(justifyright, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(justifyright, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(justifyright, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(justifycenter, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(justifycenter, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(justifycenter, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(justifycenter, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(justifycenter, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(justifyfull, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(justifyfull, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(justifyfull, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(justifyfull, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(justifyfull, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(removeformat, false, null) with <b>a[b]c</b>: calling execCommand
+[PASS] ChildDocument.execCommand(removeformat, false, null) with <b>a[b]c</b>: checking event on focused document
+[PASS] ChildDocument.execCommand(removeformat, false, null) with <b>a[b]c</b>: checking event on executed document
+[PASS] ChildDocument.execCommand(removeformat, false, null) with <b>a[b]c</b>: checking result content in focused document
+[PASS] ChildDocument.execCommand(removeformat, false, null) with <b>a[b]c</b>: checking result content in executed document
+[PASS] ChildDocument.execCommand(unlink, false, null) with <a href="foo.html">a[b]c</a>: calling execCommand
+[PASS] ChildDocument.execCommand(unlink, false, null) with <a href="foo.html">a[b]c</a>: checking event on focused document
+[PASS] ChildDocument.execCommand(unlink, false, null) with <a href="foo.html">a[b]c</a>: checking event on executed document
+[PASS] ChildDocument.execCommand(unlink, false, null) with <a href="foo.html">a[b]c</a>: checking result content in focused document
+[PASS] ChildDocument.execCommand(unlink, false, null) with <a href="foo.html">a[b]c</a>: checking result content in executed document
+[PASS] ChildDocument.execCommand(insertorderedlist, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(insertorderedlist, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(insertorderedlist, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(insertorderedlist, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(insertorderedlist, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(insertunorderedlist, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(insertunorderedlist, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(insertunorderedlist, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(insertunorderedlist, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(insertunorderedlist, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(insertparagraph, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(insertparagraph, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(insertparagraph, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(insertparagraph, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(insertparagraph, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(insertlinebreak, false, null) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(insertlinebreak, false, null) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(insertlinebreak, false, null) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(insertlinebreak, false, null) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(insertlinebreak, false, null) with a[b]c: checking result content in executed document
+[PASS] ChildDocument.execCommand(formatblock, false, div) with a[b]c: calling execCommand
+[PASS] ChildDocument.execCommand(formatblock, false, div) with a[b]c: checking event on focused document
+[PASS] ChildDocument.execCommand(formatblock, false, div) with a[b]c: checking event on executed document
+[PASS] ChildDocument.execCommand(formatblock, false, div) with a[b]c: checking result content in focused document
+[PASS] ChildDocument.execCommand(formatblock, false, div) with a[b]c: checking result content in executed document
+[FAIL] ChildDocument.execCommand(styleWithCSS, false, true): calling execCommand to initialize
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ChildDocument.execCommand(styleWithCSS, false, true): calling queryCommandState on executed document after initializing
+[PASS] ChildDocument.execCommand(styleWithCSS, false, true): calling queryCommandState on focus document after initializing
+[FAIL] ChildDocument.execCommand(styleWithCSS, false, true): calling execCommand to set state
+  assert_equals: execCommand should return false expected false but got true
+[FAIL] ChildDocument.execCommand(styleWithCSS, false, true): calling queryCommandState on executed document
+  assert_equals: queryCommandState should return undefined expected false but got true
+[PASS] ChildDocument.execCommand(styleWithCSS, false, true): calling queryCommandState on focused document
+[FAIL] ChildDocument.execCommand(styleWithCSS, false, true): calling queryCommandValue on executed document
+  assert_equals: queryCommandValue should return false expected "true" but got ""
+[FAIL] ChildDocument.execCommand(styleWithCSS, false, true): calling queryCommandState on executed document after making executed document editable
+  assert_equals: queryCommandState should return undefined expected false but got true
+[FAIL] ChildDocument.execCommand(defaultParagraphSeparator, false, div): calling execCommand to initialize
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ChildDocument.execCommand(defaultParagraphSeparator, false, div): calling queryCommandState on executed document after initializing
+[PASS] ChildDocument.execCommand(defaultParagraphSeparator, false, div): calling queryCommandState on focus document after initializing
+[FAIL] ChildDocument.execCommand(defaultParagraphSeparator, false, div): calling execCommand to set state
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ChildDocument.execCommand(defaultParagraphSeparator, false, div): calling queryCommandState on executed document
+[PASS] ChildDocument.execCommand(defaultParagraphSeparator, false, div): calling queryCommandState on focused document
+[PASS] ChildDocument.execCommand(defaultParagraphSeparator, false, div): calling queryCommandState on executed document after making executed document editable
+[FAIL] ChildDocument.execCommand(defaultParagraphSeparator, false, p): calling execCommand to initialize
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ChildDocument.execCommand(defaultParagraphSeparator, false, p): calling queryCommandState on executed document after initializing
+[PASS] ChildDocument.execCommand(defaultParagraphSeparator, false, p): calling queryCommandState on focus document after initializing
+[FAIL] ChildDocument.execCommand(defaultParagraphSeparator, false, p): calling execCommand to set state
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ChildDocument.execCommand(defaultParagraphSeparator, false, p): calling queryCommandState on executed document
+[PASS] ChildDocument.execCommand(defaultParagraphSeparator, false, p): calling queryCommandState on focused document
+[PASS] ChildDocument.execCommand(defaultParagraphSeparator, false, p): calling queryCommandState on executed document after making executed document editable
+[PASS] ParentDocument.execCommand(bold, false, bold) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(bold, false, bold) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(bold, false, bold) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(bold, false, bold) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(bold, false, bold) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(italic, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(italic, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(italic, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(italic, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(italic, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(underline, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(underline, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(underline, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(underline, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(underline, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(strikethrough, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(strikethrough, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(strikethrough, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(strikethrough, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(strikethrough, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(subscript, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(subscript, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(subscript, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(subscript, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(subscript, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(superscript, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(superscript, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(superscript, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(superscript, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(superscript, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(cut, false, null) with ab[]c: calling execCommand
+[PASS] ParentDocument.execCommand(cut, false, null) with ab[]c: checking event on focused document
+[FAIL] ParentDocument.execCommand(cut, false, null) with ab[]c: checking event on executed document
+  assert_equals: "cut" event should be fired expected true but got false
+[PASS] ParentDocument.execCommand(cut, false, null) with ab[]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(cut, false, null) with ab[]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(cut, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(cut, false, null) with a[b]c: checking event on focused document
+[FAIL] ParentDocument.execCommand(cut, false, null) with a[b]c: checking event on executed document
+  assert_equals: "cut" event should be fired expected true but got false
+[PASS] ParentDocument.execCommand(cut, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(cut, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(copy, false, null) with ab[]c: calling execCommand
+[PASS] ParentDocument.execCommand(copy, false, null) with ab[]c: checking event on focused document
+[FAIL] ParentDocument.execCommand(copy, false, null) with ab[]c: checking event on executed document
+  assert_equals: "copy" event should be fired expected true but got false
+[PASS] ParentDocument.execCommand(copy, false, null) with ab[]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(copy, false, null) with ab[]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(copy, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(copy, false, null) with a[b]c: checking event on focused document
+[FAIL] ParentDocument.execCommand(copy, false, null) with a[b]c: checking event on executed document
+  assert_equals: "copy" event should be fired expected true but got false
+[PASS] ParentDocument.execCommand(copy, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(copy, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(delete, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(delete, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(delete, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(delete, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(delete, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(forwarddelete, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(forwarddelete, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(forwarddelete, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(forwarddelete, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(forwarddelete, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(selectall, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(selectall, false, null) with a[b]c: checking unexpected synchronous event
+[PASS] ParentDocument.execCommand(selectall, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(selectall, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(selectall, false, null) with a[b]c: checking result content in executed document
+[FAIL] ParentDocument.execCommand(undo, false, null) with a[b]c: calling execCommand
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ParentDocument.execCommand(undo, false, null) with a[b]c: checking event on focused document
+[FAIL] ParentDocument.execCommand(undo, false, null) with a[b]c: checking event on executed document
+  assert_equals: "input" event should not be fired expected false but got true
+[PASS] ParentDocument.execCommand(undo, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(undo, false, null) with a[b]c: checking result content in executed document
+[FAIL] ParentDocument.execCommand(redo, false, null) with a[b]c: calling execCommand
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ParentDocument.execCommand(redo, false, null) with a[b]c: checking event on focused document
+[FAIL] ParentDocument.execCommand(redo, false, null) with a[b]c: checking event on executed document
+  assert_equals: "input" event should not be fired expected false but got true
+[PASS] ParentDocument.execCommand(redo, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(redo, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(indent, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(indent, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(indent, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(indent, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(indent, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(outdent, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(outdent, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(outdent, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(outdent, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(outdent, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(backcolor, false, #000000) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(backcolor, false, #000000) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(backcolor, false, #000000) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(backcolor, false, #000000) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(backcolor, false, #000000) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(forecolor, false, #F0F0F0) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(forecolor, false, #F0F0F0) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(forecolor, false, #F0F0F0) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(forecolor, false, #F0F0F0) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(forecolor, false, #F0F0F0) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(hilitecolor, false, #FFFF00) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(hilitecolor, false, #FFFF00) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(hilitecolor, false, #FFFF00) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(hilitecolor, false, #FFFF00) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(hilitecolor, false, #FFFF00) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(fontname, false, DummyFont) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(fontname, false, DummyFont) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(fontname, false, DummyFont) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(fontname, false, DummyFont) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(fontname, false, DummyFont) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(fontsize, false, 5) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(fontsize, false, 5) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(fontsize, false, 5) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(fontsize, false, 5) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(fontsize, false, 5) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(inserthorizontalrule, false, null) with a[]bc: calling execCommand
+[PASS] ParentDocument.execCommand(inserthorizontalrule, false, null) with a[]bc: checking event on focused document
+[PASS] ParentDocument.execCommand(inserthorizontalrule, false, null) with a[]bc: checking event on executed document
+[PASS] ParentDocument.execCommand(inserthorizontalrule, false, null) with a[]bc: checking result content in focused document
+[PASS] ParentDocument.execCommand(inserthorizontalrule, false, null) with a[]bc: checking result content in executed document
+[PASS] ParentDocument.execCommand(createlink, false, foo.html) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(createlink, false, foo.html) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(createlink, false, foo.html) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(createlink, false, foo.html) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(createlink, false, foo.html) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(insertimage, false, no-image.png) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(insertimage, false, no-image.png) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(insertimage, false, no-image.png) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(insertimage, false, no-image.png) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(insertimage, false, no-image.png) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(inserthtml, false, <b>inserted</b>) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(inserthtml, false, <b>inserted</b>) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(inserthtml, false, <b>inserted</b>) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(inserthtml, false, <b>inserted</b>) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(inserthtml, false, <b>inserted</b>) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(inserttext, false, **inserted**) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(inserttext, false, **inserted**) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(inserttext, false, **inserted**) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(inserttext, false, **inserted**) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(inserttext, false, **inserted**) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(justifyleft, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(justifyleft, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(justifyleft, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(justifyleft, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(justifyleft, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(justifyright, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(justifyright, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(justifyright, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(justifyright, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(justifyright, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(justifycenter, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(justifycenter, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(justifycenter, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(justifycenter, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(justifycenter, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(justifyfull, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(justifyfull, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(justifyfull, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(justifyfull, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(justifyfull, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(removeformat, false, null) with <b>a[b]c</b>: calling execCommand
+[PASS] ParentDocument.execCommand(removeformat, false, null) with <b>a[b]c</b>: checking event on focused document
+[PASS] ParentDocument.execCommand(removeformat, false, null) with <b>a[b]c</b>: checking event on executed document
+[PASS] ParentDocument.execCommand(removeformat, false, null) with <b>a[b]c</b>: checking result content in focused document
+[PASS] ParentDocument.execCommand(removeformat, false, null) with <b>a[b]c</b>: checking result content in executed document
+[PASS] ParentDocument.execCommand(unlink, false, null) with <a href="foo.html">a[b]c</a>: calling execCommand
+[PASS] ParentDocument.execCommand(unlink, false, null) with <a href="foo.html">a[b]c</a>: checking event on focused document
+[PASS] ParentDocument.execCommand(unlink, false, null) with <a href="foo.html">a[b]c</a>: checking event on executed document
+[PASS] ParentDocument.execCommand(unlink, false, null) with <a href="foo.html">a[b]c</a>: checking result content in focused document
+[PASS] ParentDocument.execCommand(unlink, false, null) with <a href="foo.html">a[b]c</a>: checking result content in executed document
+[PASS] ParentDocument.execCommand(insertorderedlist, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(insertorderedlist, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(insertorderedlist, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(insertorderedlist, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(insertorderedlist, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(insertunorderedlist, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(insertunorderedlist, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(insertunorderedlist, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(insertunorderedlist, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(insertunorderedlist, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(insertparagraph, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(insertparagraph, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(insertparagraph, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(insertparagraph, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(insertparagraph, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(insertlinebreak, false, null) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(insertlinebreak, false, null) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(insertlinebreak, false, null) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(insertlinebreak, false, null) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(insertlinebreak, false, null) with a[b]c: checking result content in executed document
+[PASS] ParentDocument.execCommand(formatblock, false, div) with a[b]c: calling execCommand
+[PASS] ParentDocument.execCommand(formatblock, false, div) with a[b]c: checking event on focused document
+[PASS] ParentDocument.execCommand(formatblock, false, div) with a[b]c: checking event on executed document
+[PASS] ParentDocument.execCommand(formatblock, false, div) with a[b]c: checking result content in focused document
+[PASS] ParentDocument.execCommand(formatblock, false, div) with a[b]c: checking result content in executed document
+[FAIL] ParentDocument.execCommand(styleWithCSS, false, true): calling execCommand to initialize
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ParentDocument.execCommand(styleWithCSS, false, true): calling queryCommandState on executed document after initializing
+[FAIL] ParentDocument.execCommand(styleWithCSS, false, true): calling queryCommandState on focus document after initializing
+  assert_equals: queryCommandState on focus document should return undefined expected false but got true
+[FAIL] ParentDocument.execCommand(styleWithCSS, false, true): calling execCommand to set state
+  assert_equals: execCommand should return false expected false but got true
+[FAIL] ParentDocument.execCommand(styleWithCSS, false, true): calling queryCommandState on executed document
+  assert_equals: queryCommandState should return undefined expected false but got true
+[FAIL] ParentDocument.execCommand(styleWithCSS, false, true): calling queryCommandState on focused document
+  assert_equals: queryCommandState should return undefined expected false but got true
+[FAIL] ParentDocument.execCommand(styleWithCSS, false, true): calling queryCommandValue on executed document
+  assert_equals: queryCommandValue should return false expected "true" but got ""
+[FAIL] ParentDocument.execCommand(styleWithCSS, false, true): calling queryCommandState on executed document after making executed document editable
+  assert_equals: queryCommandState should return undefined expected false but got true
+[FAIL] ParentDocument.execCommand(defaultParagraphSeparator, false, div): calling execCommand to initialize
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ParentDocument.execCommand(defaultParagraphSeparator, false, div): calling queryCommandState on executed document after initializing
+[PASS] ParentDocument.execCommand(defaultParagraphSeparator, false, div): calling queryCommandState on focus document after initializing
+[FAIL] ParentDocument.execCommand(defaultParagraphSeparator, false, div): calling execCommand to set state
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ParentDocument.execCommand(defaultParagraphSeparator, false, div): calling queryCommandState on executed document
+[PASS] ParentDocument.execCommand(defaultParagraphSeparator, false, div): calling queryCommandState on focused document
+[PASS] ParentDocument.execCommand(defaultParagraphSeparator, false, div): calling queryCommandState on executed document after making executed document editable
+[FAIL] ParentDocument.execCommand(defaultParagraphSeparator, false, p): calling execCommand to initialize
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ParentDocument.execCommand(defaultParagraphSeparator, false, p): calling queryCommandState on executed document after initializing
+[PASS] ParentDocument.execCommand(defaultParagraphSeparator, false, p): calling queryCommandState on focus document after initializing
+[FAIL] ParentDocument.execCommand(defaultParagraphSeparator, false, p): calling execCommand to set state
+  assert_equals: execCommand should return false expected false but got true
+[PASS] ParentDocument.execCommand(defaultParagraphSeparator, false, p): calling queryCommandState on executed document
+[PASS] ParentDocument.execCommand(defaultParagraphSeparator, false, p): calling queryCommandState on focused document
+[PASS] ParentDocument.execCommand(defaultParagraphSeparator, false, p): calling queryCommandState on executed document after making executed document editable
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/insertparagraph-in-non-splittable-element-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/insertparagraph-in-non-splittable-element-expected.txt
new file mode 100644
index 0000000..c64c708
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/insertparagraph-in-non-splittable-element-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+[FAIL] insertParagraph in button of <div><button>abc</button></div>
+  assert_equals: expected "<div><button><br>abc</button></div>" but got "<div><button><br></button></div><div><button>abc</button></div>"
+[FAIL] insertParagraph in caption of <div><table><caption>abc</caption><tbody><tr><td>abc</td></tr></tbody></table></div>
+  assert_equals: expected "<div><table><caption><br>abc</caption><tbody><tr><td>abc</td></tr></tbody></table></div>" but got "<div><table><caption><br></caption><caption>abc</caption><tbody><tr><td>abc</td></tr></tbody></table></div>"
+[PASS] insertParagraph in col of <div><table><colgroup><col></colgroup><tbody><tr><td>abc</td></tr></tbody></table></div>
+[PASS] insertParagraph in colgroup of <div><table><colgroup><col></colgroup><tbody><tr><td>abc</td></tr></tbody></table></div>
+[PASS] insertParagraph in iframe of <div><iframe srcdoc="abc"></iframe></div>
+[FAIL] insertParagraph in legend of <div><fieldset><legend>abc</legend></fieldset></div>
+  assert_equals: expected "<div><fieldset><legend><br>abc</legend></fieldset></div>" but got "<div><fieldset><legend><br></legend><legend>abc</legend></fieldset></div>"
+[FAIL] insertParagraph in meter of <div><meter max="100" value="50">abc</meter></div>
+  assert_equals: expected "<div><br></div><div><meter max=\"100\" value=\"50\">abc</meter></div>" but got "<div><br><meter max=\"100\" value=\"50\">abc</meter></div>"
+[PASS] insertParagraph in optgroup of <div><select><optgroup><option>abc</option></optgroup></select></div>
+[FAIL] insertParagraph in option of <div><select><option>abc</option></select></div>
+  assert_equals: expected "<div><select><option>abc</option></select></div>" but got "<div><br></div><div><select><option>abc</option></select></div>"
+[PASS] insertParagraph in progress of <div><progress max="100" value="50">abc</progress></div>
+[PASS] insertParagraph in select of <div><select><option>abc</option></select></div>
+[FAIL] insertParagraph in table of <div><table><tbody><tr><td>abc</td></tr></tbody></table></div>
+  assert_in_array: value "<div><br><table><tbody><tr><td>abc</td></tr></tbody></table></div>" not in array ["<div><table><tbody><tr><td><br>abc</td></tr></tbody></table></div>", "<div><br></div><div><table><tbody><tr><td>abc</td></tr></tbody></table></div>"]
+[PASS] insertParagraph in tbody of <div><table><tbody><tr><td>abc</td></tr></tbody></table></div>
+[PASS] insertParagraph in tr of <div><table><tbody><tr><td>abc</td></tr></tbody></table></div>
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative-expected.txt
new file mode 100644
index 0000000..e6b994b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative-expected.txt
@@ -0,0 +1,75 @@
+This is a testharness.js-based test.
+[PASS] Testing inserting content around link element
+[FAIL] Replacing text in a link in <b> with "XY" in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">XY</b></a></p>", "<p><b><a href=\"about:blank\">XY</b></a><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following Selection.collapseToEnd) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following ArrowRight key press) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following End key press) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following Selection.collapseToStart) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following ArrowLeft key press) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following Home key press) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to middle of a link in <b> (Selection.collapse) in <p><b><a href="about:blank">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abXYc</a></b></p>", "<p><b><a href=\"about:blank\">abXYc</a></b><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to middle of a link in <b> (Selection.addRange) in <p><b><a href="about:blank">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abXYc</a></b></p>", "<p><b><a href=\"about:blank\">abXYc</a></b><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to start of a link in <b> (Selection.collapse) in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a>undefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to start of a link in <b> (Selection.addRange) in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a>undefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to end of a link in <b> (Selection.collapse) in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XYundefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to end of a link in <b> (Selection.addRange) in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XYundefined<br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to middle of a link in <b> in <p><b><a href="about:blank">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abXYc</a></b></p>", "<p><b><a href=\"about:blank\">abXYc</a></b><br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to start of a link in <b> in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to end of a link in <b> in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting following character of a link in <b> (Backspace) in <p><b><a href="about:blank">abc</a>d[]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a>d</b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting following character of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">abc</a>d[]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting a previous character of a link in <b> (Delete) in <p><b>[]z<a href="about:blank">abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting a previous character of a link in <b> (execCommand("forwarddelete")) in <p><b>[]z<a href="about:blank">abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> (Backspace) in <p><b><a href="about:blank">abcd[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abcd</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p></b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">abcd[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p></b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> (Delete) in <p><b><a href="about:blank">abc[]d</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">bcd</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> (execCommand("forwarddelete")) in <p><b><a href="about:blank">abc[]d</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (Backspace) in <p><b><a href="about:blank">z[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">zabc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">z[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (Delete) in <p><b><a href="about:blank">[]zabc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (execCommand("forwarddelete")) in <p><b><a href="about:blank">[]zabc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has a class for bold text in <p><b><a href="about:blank" class="bold">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has a class for bold text in <p><b><a href="about:blank" class="bold">abc[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has inline style for bold text in <p><b><a href="about:blank" style="font-weight: bold">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has inline style for bold text in <p><b><a href="about:blank" style="font-weight: bold">abc[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has a class for bold text (in CSS mode) in <p><b><a href="about:blank" class="bold">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has a class for bold text (in CSS mode) in <p><b><a href="about:blank" class="bold">abc[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has inline style for bold text (in CSS mode) in <p><b><a href="about:blank" style="font-weight: bold">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has inline style for bold text (in CSS mode) in <p><b><a href="about:blank" style="font-weight: bold">abc[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b><br></p>"]
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode-expected.txt
new file mode 100644
index 0000000..5a72184
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode-expected.txt
@@ -0,0 +1,75 @@
+This is a testharness.js-based test.
+[PASS] Testing inserting content around link element
+[FAIL] Replacing text in a link with "XY" in <p>[abc]</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">XY</a></p>", "<p><a href=\"about:blank\">XY</a><br></p>"]
+[FAIL] Inserting "XY" after making a link (following Selection.collapseToEnd) in <p>[abc]</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after making a link (following ArrowRight key press) in <p>[abc]</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after making a link (following End key press) in <p>[abc]</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after making a link (following Selection.collapseToStart) in <p>[abc]</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after making a link (following ArrowLeft key press) in <p>[abc]</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after making a link (following Home key press) in <p>[abc]</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to middle of a link (Selection.collapse) in <p><a href="about:blank">[]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abXYc</a></p>", "<p><a href=\"about:blank\">abXYc</a><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to middle of a link (Selection.addRange) in <p><a href="about:blank">[]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abXYc</a></p>", "<p><a href=\"about:blank\">abXYc</a><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to start of a link (Selection.collapse) in <p><a href="about:blank">ab[]c</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a>undefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to start of a link (Selection.addRange) in <p><a href="about:blank">ab[]c</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a>undefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to end of a link (Selection.collapse) in <p><a href="about:blank">ab[]c</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XYundefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to end of a link (Selection.addRange) in <p><a href="about:blank">ab[]c</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XYundefined<br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to middle of a link in <p><a href="about:blank">[]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abXYc</a></p>", "<p><a href=\"about:blank\">abXYc</a><br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to start of a link in <p><a href="about:blank">ab[]c</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to end of a link in <p><a href="about:blank">ab[]c</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after deleting following character of a link (Backspace) in <p><a href="about:blank">abc</a>d[]</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a>d</p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after deleting following character of a link (execCommand("delete")) in <p><a href="about:blank">abc</a>d[]</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after deleting a previous character of a link (Delete) in <p>[]z<a href="about:blank">abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after deleting a previous character of a link (execCommand("forwarddelete")) in <p>[]z<a href="about:blank">abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link (Backspace) in <p><a href="about:blank">abcd[]</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abcd</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link (execCommand("delete")) in <p><a href="about:blank">abcd[]</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link (Delete) in <p><a href="about:blank">abc[]d</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">bcd</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link (execCommand("forwarddelete")) in <p><a href="about:blank">abc[]d</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link (Backspace) in <p><a href="about:blank">z[]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">zabc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link (execCommand("delete")) in <p><a href="about:blank">z[]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link (Delete) in <p><a href="about:blank">[]zabc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link (execCommand("forwarddelete")) in <p><a href="about:blank">[]zabc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has a class for bold text in <p><a href="about:blank" class="bold">[]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" class=\"bold\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\" class=\"bold\">abc</a></p>", "<p>XY<a href=\"about:blank\" class=\"bold\">abc</a><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has a class for bold text in <p><a href="about:blank" class="bold">abc[]</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" class=\"bold\">abc</a></p>" not in array ["<p><a href=\"about:blank\" class=\"bold\">abc</a>XY</p>", "<p><a href=\"about:blank\" class=\"bold\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" at start of a link which has inline style for bold text in <p><a href="about:blank" style="font-weight: bold">[]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></p>", "<p>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has inline style for bold text in <p><a href="about:blank" style="font-weight: bold">abc[]</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></p>" not in array ["<p><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</p>", "<p><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" at start of a link which has a class for bold text (in CSS mode) in <p><a href="about:blank" class="bold">[]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" class=\"bold\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\" class=\"bold\">abc</a></p>", "<p>XY<a href=\"about:blank\" class=\"bold\">abc</a><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has a class for bold text (in CSS mode) in <p><a href="about:blank" class="bold">abc[]</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" class=\"bold\">abc</a></p>" not in array ["<p><a href=\"about:blank\" class=\"bold\">abc</a>XY</p>", "<p><a href=\"about:blank\" class=\"bold\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" at start of a link which has inline style for bold text (in CSS mode) in <p><a href="about:blank" style="font-weight: bold">[]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></p>", "<p>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has inline style for bold text (in CSS mode) in <p><a href="about:blank" style="font-weight: bold">abc[]</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></p>" not in array ["<p><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</p>", "<p><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY<br></p>"]
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_child=b-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_child=b-expected.txt
new file mode 100644
index 0000000..6e9d34222
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_child=b-expected.txt
@@ -0,0 +1,61 @@
+This is a testharness.js-based test.
+[PASS] Testing inserting content around link element
+[FAIL] Inserting "XY" after setting caret position to middle of a link containing <b> (Selection.collapse) in <p><a href="about:blank"><b>[]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><a href=\"about:blank\"><b>abXYc</b></a></p>", "<p><a href=\"about:blank\"><b>abXYc</b></a><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to middle of a link containing <b> (Selection.addRange) in <p><a href="about:blank"><b>[]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><a href=\"about:blank\"><b>abXYc</b></a></p>", "<p><a href=\"about:blank\"><b>abXYc</b></a><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to start of a link containing <b> (Selection.collapse) in <p><a href="about:blank"><b>ab[]c</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a>undefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to start of a link containing <b> (Selection.addRange) in <p><a href="about:blank"><b>ab[]c</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a>undefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to end of a link containing <b> (Selection.collapse) in <p><a href="about:blank"><b>ab[]c</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XYundefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to end of a link containing <b> (Selection.addRange) in <p><a href="about:blank"><b>ab[]c</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XYundefined<br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to middle of a link containing <b> in <p><a href="about:blank"><b>[]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><a href=\"about:blank\"><b>abXYc</b></a></p>", "<p><a href=\"about:blank\"><b>abXYc</b></a><br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to start of a link containing <b> in <p><a href="about:blank"><b>ab[]c</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to end of a link containing <b> in <p><a href="about:blank"><b>ab[]c</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting following character of a link containing <b> (Backspace) in <p><a href="about:blank"><b>abc</b></a>d[]</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a>d</p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting following character of a link containing <b> (execCommand("delete")) in <p><a href="about:blank"><b>abc</b></a>d[]</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting a previous character of a link containing <b> (Delete) in <p>[]z<a href="about:blank"><b>abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting a previous character of a link containing <b> (execCommand("forwarddelete")) in <p>[]z<a href="about:blank"><b>abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link containing <b> (Backspace) in <p><a href="about:blank"><b>abcd[]</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abcd</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p></b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link containing <b> (execCommand("delete")) in <p><a href="about:blank"><b>abcd[]</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p></b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link containing <b> (Delete) in <p><a href="about:blank"><b>abc[]d</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>bcd</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link containing <b> (execCommand("forwarddelete")) in <p><a href="about:blank"><b>abc[]d</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link containing <b> (Backspace) in <p><a href="about:blank"><b>z[]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>zabc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link containing <b> (execCommand("delete")) in <p><a href="about:blank"><b>z[]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link containing <b> (Delete) in <p><a href="about:blank"><b>[]zabc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link containing <b> (execCommand("forwarddelete")) in <p><a href="about:blank"><b>[]zabc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has a class for bold text in <p><a href="about:blank" class="bold"><b>[]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" class=\"bold\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has a class for bold text in <p><a href="about:blank" class="bold"><b>abc[]</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" class=\"bold\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has inline style for bold text in <p><a href="about:blank" style="font-weight: bold"><b>[]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" style=\"font-weight: bold\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has inline style for bold text in <p><a href="about:blank" style="font-weight: bold"><b>abc[]</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" style=\"font-weight: bold\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has a class for bold text (in CSS mode) in <p><a href="about:blank" class="bold"><b>[]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" class=\"bold\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has a class for bold text (in CSS mode) in <p><a href="about:blank" class="bold"><b>abc[]</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" class=\"bold\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has inline style for bold text (in CSS mode) in <p><a href="about:blank" style="font-weight: bold"><b>[]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" style=\"font-weight: bold\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has inline style for bold text (in CSS mode) in <p><a href="about:blank" style="font-weight: bold"><b>abc[]</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\" style=\"font-weight: bold\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b><br></p>"]
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_parent=b-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_parent=b-expected.txt
new file mode 100644
index 0000000..e6b994b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_parent=b-expected.txt
@@ -0,0 +1,75 @@
+This is a testharness.js-based test.
+[PASS] Testing inserting content around link element
+[FAIL] Replacing text in a link in <b> with "XY" in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">XY</b></a></p>", "<p><b><a href=\"about:blank\">XY</b></a><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following Selection.collapseToEnd) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following ArrowRight key press) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following End key press) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following Selection.collapseToStart) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following ArrowLeft key press) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after making a link in <b> (following Home key press) in <p><b>[abc]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to middle of a link in <b> (Selection.collapse) in <p><b><a href="about:blank">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abXYc</a></b></p>", "<p><b><a href=\"about:blank\">abXYc</a></b><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to middle of a link in <b> (Selection.addRange) in <p><b><a href="about:blank">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abXYc</a></b></p>", "<p><b><a href=\"about:blank\">abXYc</a></b><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to start of a link in <b> (Selection.collapse) in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a>undefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to start of a link in <b> (Selection.addRange) in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a>undefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to end of a link in <b> (Selection.collapse) in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XYundefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to end of a link in <b> (Selection.addRange) in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XYundefined<br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to middle of a link in <b> in <p><b><a href="about:blank">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abXYc</a></b></p>", "<p><b><a href=\"about:blank\">abXYc</a></b><br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to start of a link in <b> in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to end of a link in <b> in <p><b><a href="about:blank">ab[]c</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting following character of a link in <b> (Backspace) in <p><b><a href="about:blank">abc</a>d[]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a>d</b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting following character of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">abc</a>d[]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting a previous character of a link in <b> (Delete) in <p><b>[]z<a href="about:blank">abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting a previous character of a link in <b> (execCommand("forwarddelete")) in <p><b>[]z<a href="about:blank">abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> (Backspace) in <p><b><a href="about:blank">abcd[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abcd</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p></b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">abcd[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p></b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> (Delete) in <p><b><a href="about:blank">abc[]d</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">bcd</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> (execCommand("forwarddelete")) in <p><b><a href="about:blank">abc[]d</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (Backspace) in <p><b><a href="about:blank">z[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">zabc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">z[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (Delete) in <p><b><a href="about:blank">[]zabc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (execCommand("forwarddelete")) in <p><b><a href="about:blank">[]zabc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has a class for bold text in <p><b><a href="about:blank" class="bold">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has a class for bold text in <p><b><a href="about:blank" class="bold">abc[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has inline style for bold text in <p><b><a href="about:blank" style="font-weight: bold">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has inline style for bold text in <p><b><a href="about:blank" style="font-weight: bold">abc[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has a class for bold text (in CSS mode) in <p><b><a href="about:blank" class="bold">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" class=\"bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has a class for bold text (in CSS mode) in <p><b><a href="about:blank" class="bold">abc[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" class=\"bold\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has inline style for bold text (in CSS mode) in <p><b><a href="about:blank" style="font-weight: bold">[]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has inline style for bold text (in CSS mode) in <p><b><a href="about:blank" style="font-weight: bold">abc[]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</b><br></p>"]
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_parent=b_child=i-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_parent=b_child=i-expected.txt
new file mode 100644
index 0000000..8bb0f6c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-collapsed-selection.tentative_target=DesignMode_parent=b_child=i-expected.txt
@@ -0,0 +1,61 @@
+This is a testharness.js-based test.
+[PASS] Testing inserting content around link element
+[FAIL] Inserting "XY" after setting caret position to middle of a link in <b> and containing <i> (Selection.collapse) in <p><b><a href="about:blank"><i>[]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><a href=\"about:blank\"><i>abXYc</i></a></b></p>", "<p><b><a href=\"about:blank\"><i>abXYc</i></a></b><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to middle of a link in <b> and containing <i> (Selection.addRange) in <p><b><a href="about:blank"><i>[]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><a href=\"about:blank\"><i>abXYc</i></a></b></p>", "<p><b><a href=\"about:blank\"><i>abXYc</i></a></b><br></p>"]
+[FAIL] Inserting "XY" after setting caret position to start of a link in <b> and containing <i> (Selection.collapse) in <p><b><a href="about:blank"><i>ab[]c</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a>undefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to start of a link in <b> and containing <i> (Selection.addRange) in <p><b><a href="about:blank"><i>ab[]c</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a>undefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to end of a link in <b> and containing <i> (Selection.collapse) in <p><b><a href="about:blank"><i>ab[]c</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\">abc</a>XYundefined<br></p>"]
+[FAIL] Inserting "XY" after setting caret position to end of a link in <b> and containing <i> (Selection.addRange) in <p><b><a href="about:blank"><i>ab[]c</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\">abc</a>XYundefined<br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to middle of a link in <b> and containing <i> in <p><b><a href="about:blank"><i>[]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><a href=\"about:blank\"><i>abXYc</i></a></b></p>", "<p><b><a href=\"about:blank\"><i>abXYc</i></a></b><br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to start of a link in <b> and containing <i> in <p><b><a href="about:blank"><i>ab[]c</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" after modifying caret position to end of a link in <b> and containing <i> in <p><b><a href="about:blank"><i>ab[]c</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting following character of a link in <b> and containing <i> (Backspace) in <p><b><a href="about:blank"><i>abc</i></a>d[]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a>d</b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting following character of a link in <b> and containing <i> (execCommand("delete")) in <p><b><a href="about:blank"><i>abc</i></a>d[]</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting a previous character of a link in <b> and containing <i> (Delete) in <p><b>[]z<a href="about:blank"><i>abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting a previous character of a link in <b> and containing <i> (execCommand("forwarddelete")) in <p><b>[]z<a href="about:blank"><i>abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> and containing <i> (Backspace) in <p><b><a href="about:blank"><i>abcd[]</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abcd</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p></i></b><a href=\"about:blank\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> and containing <i> (execCommand("delete")) in <p><b><a href="about:blank"><i>abcd[]</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p></i></b><a href=\"about:blank\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> and containing <i> (Delete) in <p><b><a href="about:blank"><i>abc[]d</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>bcd</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character of a link in <b> and containing <i> (execCommand("forwarddelete")) in <p><b><a href="about:blank"><i>abc[]d</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> and containing <i> (Backspace) in <p><b><a href="about:blank"><i>z[]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>zabc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> and containing <i> (execCommand("delete")) in <p><b><a href="about:blank"><i>z[]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> and containing <i> (Delete) in <p><b><a href="about:blank"><i>[]zabc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> and containing <i> (execCommand("forwarddelete")) in <p><b><a href="about:blank"><i>[]zabc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has a class for bold text in <p><b><a href="about:blank" class="bold"><i>[]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\" class=\"bold\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\" class=\"bold\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has a class for bold text in <p><b><a href="about:blank" class="bold"><i>abc[]</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\" class=\"bold\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\" class=\"bold\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has inline style for bold text in <p><b><a href="about:blank" style="font-weight: bold"><i>[]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has inline style for bold text in <p><b><a href="about:blank" style="font-weight: bold"><i>abc[]</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has a class for bold text (in CSS mode) in <p><b><a href="about:blank" class="bold"><i>[]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\" class=\"bold\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\" class=\"bold\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has a class for bold text (in CSS mode) in <p><b><a href="about:blank" class="bold"><i>abc[]</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" class=\"bold\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\" class=\"bold\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\" class=\"bold\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" at start of a link which has inline style for bold text (in CSS mode) in <p><b><a href="about:blank" style="font-weight: bold"><i>[]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\" style=\"font-weight: bold\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" at end of a link which has inline style for bold text (in CSS mode) in <p><b><a href="about:blank" style="font-weight: bold"><i>abc[]</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\" style=\"font-weight: bold\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\" style=\"font-weight: bold\">abc</a>XY</i></b><br></p>"]
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative-expected.txt
new file mode 100644
index 0000000..0e08db5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative-expected.txt
@@ -0,0 +1,43 @@
+This is a testharness.js-based test.
+[PASS] Testing inserting content at non-collapsed selection around link element
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (Direct typing) in <p><b><a href="about:blank">[z]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">zabc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">XYabc</a></b></p>", "<p><b><a href=\"about:blank\">XYabc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> (Direct typing) in <p><b><a href="about:blank">abc[d]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abcd</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abcXY</a></b></p>", "<p><b><a href=\"about:blank\">abcXY</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> (Direct typing) in <p><b><a href="about:blank">ab[cd</a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abcd</a>def</b></p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XYf</b></p>", "<p><b><a href=\"about:blank\">ab</a>XYf</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> (Direct typing) in <p><b>a[bc<a href="about:blank">de]f</a></b></p>
+  assert_in_array: value "<p><b>YXabc<a href=\"about:blank\">def</a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\">f</a></b></p>", "<p><b>aXY<a href=\"about:blank\">f</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (Backspace) in <p><b><a href="about:blank">[z]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">zabc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> (Backspace) in <p><b><a href="about:blank">abc[d]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abcd</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> (Backspace) in <p><b><a href="about:blank">ab[cd</a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abcd</a>def</b></p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XYf</b></p>", "<p><b><a href=\"about:blank\">ab</a>XYf</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> (Backspace) in <p><b>a[bc<a href="about:blank">de]f</a></b></p>
+  assert_in_array: value "<p><b>YXabc<a href=\"about:blank\">def</a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\">f</a></b></p>", "<p><b>aXY<a href=\"about:blank\">f</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (Delete) in <p><b><a href="about:blank">[z]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> (Delete) in <p><b><a href="about:blank">abc[d]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">bcd</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> (Delete) in <p><b><a href="about:blank">ab[cd</a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">bcd</a>def</b></p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XYf</b></p>", "<p><b><a href=\"about:blank\">ab</a>XYf</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> (Delete) in <p><b>a[bc<a href="about:blank">de]f</a></b></p>
+  assert_in_array: value "<p><b>YXbc<a href=\"about:blank\">def</a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\">f</a></b></p>", "<p><b>aXY<a href=\"about:blank\">f</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">[z]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">abc[d]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">ab[cd</a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">ab</a>f</b></p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XYf</b></p>", "<p><b><a href=\"about:blank\">ab</a>XYf</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> (execCommand("delete")) in <p><b>a[bc<a href="about:blank">de]f</a></b></p>
+  assert_in_array: value "<p><b>YXa<a href=\"about:blank\">f</a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\">f</a></b></p>", "<p><b>aXY<a href=\"about:blank\">f</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (execCommand("forwarddelete")) in <p><b><a href="about:blank">[z]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> (execCommand("forwarddelete")) in <p><b><a href="about:blank">abc[d]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> (execCommand("forwarddelete")) in <p><b><a href="about:blank">ab[cd</a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">ab</a>f</b></p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XYf</b></p>", "<p><b><a href=\"about:blank\">ab</a>XYf</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> (execCommand("forwarddelete")) in <p><b>a[bc<a href="about:blank">de]f</a></b></p>
+  assert_in_array: value "<p><b>YXa<a href=\"about:blank\">f</a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\">f</a></b></p>", "<p><b>aXY<a href=\"about:blank\">f</a></b><br></p>"]
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode-expected.txt
new file mode 100644
index 0000000..54e3858
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode-expected.txt
@@ -0,0 +1,63 @@
+This is a testharness.js-based test.
+[PASS] Testing inserting content at non-collapsed selection around link element
+[FAIL] Inserting "XY" after deleting first character of a link (Direct typing) in <p><a href="about:blank">[z]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">zabc</a></p>" not in array ["<p><a href=\"about:blank\">XYabc</a></p>", "<p><a href=\"about:blank\">XYabc</a><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link (Direct typing) in <p><a href="about:blank">abc[d]</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abcd</a></p>" not in array ["<p><a href=\"about:blank\">abcXY</a></p>", "<p><a href=\"about:blank\">abcXY</a><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link (Direct typing) in <p><a href="about:blank">ab[cd</a>de]f</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abcd</a>def</p>" not in array ["<p><a href=\"about:blank\">ab</a>XYf</p>", "<p><a href=\"about:blank\">ab</a>XYf<br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link (Direct typing) in <p>a[bc<a href="about:blank">de]f</a></p>
+  assert_in_array: value "<p>YXabc<a href=\"about:blank\">def</a></p>" not in array ["<p>aXY<a href=\"about:blank\">f</a></p>", "<p>aXY<a href=\"about:blank\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting text between 2 same links (Direct typing) in <p><a href="about:blank">a[bc</a><a href="about:blank">de]f</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a><a href=\"about:blank\">def</a></p>" not in array ["<p><a href=\"about:blank\">a</a>XY<a href=\"about:blank\">f</a></p>", "<p><a href=\"about:blank\">a</a>XY<a href=\"about:blank\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting text between 2 different links (Direct typing) in <p><a href="about:blank">a[bc</a><a href="http://example.com/">de]f</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a><a href=\"http://example.com/\">def</a></p>" not in array ["<p><a href=\"about:blank\">a</a>XY<a href=\"http://example.com/\">f</a></p>", "<p><a href=\"about:blank\">a</a>XY<a href=\"http://example.com/\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link (Backspace) in <p><a href="about:blank">[z]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">zabc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link (Backspace) in <p><a href="about:blank">abc[d]</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abcd</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link (Backspace) in <p><a href="about:blank">ab[cd</a>de]f</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abcd</a>def</p>" not in array ["<p><a href=\"about:blank\">ab</a>XYf</p>", "<p><a href=\"about:blank\">ab</a>XYf<br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link (Backspace) in <p>a[bc<a href="about:blank">de]f</a></p>
+  assert_in_array: value "<p>YXabc<a href=\"about:blank\">def</a></p>" not in array ["<p>aXY<a href=\"about:blank\">f</a></p>", "<p>aXY<a href=\"about:blank\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting text between 2 same links (Backspace) in <p><a href="about:blank">a[bc</a><a href="about:blank">de]f</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a><a href=\"about:blank\">def</a></p>" not in array ["<p><a href=\"about:blank\">a</a>XY<a href=\"about:blank\">f</a></p>", "<p><a href=\"about:blank\">a</a>XY<a href=\"about:blank\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting text between 2 different links (Backspace) in <p><a href="about:blank">a[bc</a><a href="http://example.com/">de]f</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a><a href=\"http://example.com/\">def</a></p>" not in array ["<p><a href=\"about:blank\">a</a>XY<a href=\"http://example.com/\">f</a></p>", "<p><a href=\"about:blank\">a</a>XY<a href=\"http://example.com/\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link (Delete) in <p><a href="about:blank">[z]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link (Delete) in <p><a href="about:blank">abc[d]</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">bcd</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link (Delete) in <p><a href="about:blank">ab[cd</a>de]f</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">bcd</a>def</p>" not in array ["<p><a href=\"about:blank\">ab</a>XYf</p>", "<p><a href=\"about:blank\">ab</a>XYf<br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link (Delete) in <p>a[bc<a href="about:blank">de]f</a></p>
+  assert_in_array: value "<p>YXbc<a href=\"about:blank\">def</a></p>" not in array ["<p>aXY<a href=\"about:blank\">f</a></p>", "<p>aXY<a href=\"about:blank\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting text between 2 same links (Delete) in <p><a href="about:blank">a[bc</a><a href="about:blank">de]f</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">bc</a><a href=\"about:blank\">def</a></p>" not in array ["<p><a href=\"about:blank\">a</a>XY<a href=\"about:blank\">f</a></p>", "<p><a href=\"about:blank\">a</a>XY<a href=\"about:blank\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting text between 2 different links (Delete) in <p><a href="about:blank">a[bc</a><a href="http://example.com/">de]f</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">bc</a><a href=\"http://example.com/\">def</a></p>" not in array ["<p><a href=\"about:blank\">a</a>XY<a href=\"http://example.com/\">f</a></p>", "<p><a href=\"about:blank\">a</a>XY<a href=\"http://example.com/\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link (execCommand("delete")) in <p><a href="about:blank">[z]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link (execCommand("delete")) in <p><a href="about:blank">abc[d]</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link (execCommand("delete")) in <p><a href="about:blank">ab[cd</a>de]f</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">ab</a>f</p>" not in array ["<p><a href=\"about:blank\">ab</a>XYf</p>", "<p><a href=\"about:blank\">ab</a>XYf<br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link (execCommand("delete")) in <p>a[bc<a href="about:blank">de]f</a></p>
+  assert_in_array: value "<p>YXa<a href=\"about:blank\">f</a></p>" not in array ["<p>aXY<a href=\"about:blank\">f</a></p>", "<p>aXY<a href=\"about:blank\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting text between 2 same links (execCommand("delete")) in <p><a href="about:blank">a[bc</a><a href="about:blank">de]f</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">a</a><a href=\"about:blank\">f</a></p>" not in array ["<p><a href=\"about:blank\">a</a>XY<a href=\"about:blank\">f</a></p>", "<p><a href=\"about:blank\">a</a>XY<a href=\"about:blank\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting text between 2 different links (execCommand("delete")) in <p><a href="about:blank">a[bc</a><a href="http://example.com/">de]f</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">a</a><a href=\"http://example.com/\">f</a></p>" not in array ["<p><a href=\"about:blank\">a</a>XY<a href=\"http://example.com/\">f</a></p>", "<p><a href=\"about:blank\">a</a>XY<a href=\"http://example.com/\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link (execCommand("forwarddelete")) in <p><a href="about:blank">[z]abc</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p>XY<a href=\"about:blank\">abc</a></p>", "<p>XY<a href=\"about:blank\">abc</a><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link (execCommand("forwarddelete")) in <p><a href="about:blank">abc[d]</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">abc</a></p>" not in array ["<p><a href=\"about:blank\">abc</a>XY</p>", "<p><a href=\"about:blank\">abc</a>XY<br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link (execCommand("forwarddelete")) in <p><a href="about:blank">ab[cd</a>de]f</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">ab</a>f</p>" not in array ["<p><a href=\"about:blank\">ab</a>XYf</p>", "<p><a href=\"about:blank\">ab</a>XYf<br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link (execCommand("forwarddelete")) in <p>a[bc<a href="about:blank">de]f</a></p>
+  assert_in_array: value "<p>YXa<a href=\"about:blank\">f</a></p>" not in array ["<p>aXY<a href=\"about:blank\">f</a></p>", "<p>aXY<a href=\"about:blank\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting text between 2 same links (execCommand("forwarddelete")) in <p><a href="about:blank">a[bc</a><a href="about:blank">de]f</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">a</a><a href=\"about:blank\">f</a></p>" not in array ["<p><a href=\"about:blank\">a</a>XY<a href=\"about:blank\">f</a></p>", "<p><a href=\"about:blank\">a</a>XY<a href=\"about:blank\">f</a><br></p>"]
+[FAIL] Inserting "XY" after deleting text between 2 different links (execCommand("forwarddelete")) in <p><a href="about:blank">a[bc</a><a href="http://example.com/">de]f</a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\">a</a><a href=\"http://example.com/\">f</a></p>" not in array ["<p><a href=\"about:blank\">a</a>XY<a href=\"http://example.com/\">f</a></p>", "<p><a href=\"about:blank\">a</a>XY<a href=\"http://example.com/\">f</a><br></p>"]
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_child=b-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_child=b-expected.txt
new file mode 100644
index 0000000..2645b9d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_child=b-expected.txt
@@ -0,0 +1,43 @@
+This is a testharness.js-based test.
+[PASS] Testing inserting content at non-collapsed selection around link element
+[FAIL] Inserting "XY" after deleting first character of a link containing <b> (Direct typing) in <p><a href="about:blank"><b>[z]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>zabc</b></a></p>" not in array ["<p><a href=\"about:blank\"><b>XYabc</b></a></p>", "<p><a href=\"about:blank\"><b>XYabc</b></a><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link containing <b> (Direct typing) in <p><a href="about:blank"><b>abc[d]</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abcd</b></a></p>" not in array ["<p><a href=\"about:blank\"><b>abcXY</b></a></p>", "<p><a href=\"about:blank\"><b>abcXY</b></a><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link containing <b> (Direct typing) in <p><a href="about:blank"><b>ab[cd</b></a>de]f</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abcd</b></a>def</p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XY</b>f</p>", "<p><b><a href=\"about:blank\">ab</a>XY</b>f<br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link containing <b> (Direct typing) in <p>a[bc<a href="about:blank"><b>de]f</b></a></p>
+  assert_in_array: value "<p>YXabc<a href=\"about:blank\"><b>def</b></a></p>" not in array ["<p>aXY<a href=\"about:blank\"><b>f</b></a></p>", "<p>aXY<a href=\"about:blank\"><b>f</b></a><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link containing <b> (Backspace) in <p><a href="about:blank"><b>[z]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>zabc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link containing <b> (Backspace) in <p><a href="about:blank"><b>abc[d]</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abcd</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link containing <b> (Backspace) in <p><a href="about:blank"><b>ab[cd</b></a>de]f</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abcd</b></a>def</p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XY</b>f</p>", "<p><b><a href=\"about:blank\">ab</a>XY</b>f<br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link containing <b> (Backspace) in <p>a[bc<a href="about:blank"><b>de]f</b></a></p>
+  assert_in_array: value "<p>YXabc<a href=\"about:blank\"><b>def</b></a></p>" not in array ["<p>aXY<a href=\"about:blank\"><b>f</b></a></p>", "<p>aXY<a href=\"about:blank\"><b>f</b></a><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link containing <b> (Delete) in <p><a href="about:blank"><b>[z]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link containing <b> (Delete) in <p><a href="about:blank"><b>abc[d]</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>bcd</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link containing <b> (Delete) in <p><a href="about:blank"><b>ab[cd</b></a>de]f</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>bcd</b></a>def</p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XY</b>f</p>", "<p><b><a href=\"about:blank\">ab</a>XY</b>f<br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link containing <b> (Delete) in <p>a[bc<a href="about:blank"><b>de]f</b></a></p>
+  assert_in_array: value "<p>YXbc<a href=\"about:blank\"><b>def</b></a></p>" not in array ["<p>aXY<a href=\"about:blank\"><b>f</b></a></p>", "<p>aXY<a href=\"about:blank\"><b>f</b></a><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link containing <b> (execCommand("delete")) in <p><a href="about:blank"><b>[z]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link containing <b> (execCommand("delete")) in <p><a href="about:blank"><b>abc[d]</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link containing <b> (execCommand("delete")) in <p><a href="about:blank"><b>ab[cd</b></a>de]f</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>ab</b></a>f</p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XY</b>f</p>", "<p><b><a href=\"about:blank\">ab</a>XY</b>f<br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link containing <b> (execCommand("delete")) in <p>a[bc<a href="about:blank"><b>de]f</b></a></p>
+  assert_in_array: value "<p>YXa<a href=\"about:blank\"><b>f</b></a></p>" not in array ["<p>aXY<a href=\"about:blank\"><b>f</b></a></p>", "<p>aXY<a href=\"about:blank\"><b>f</b></a><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link containing <b> (execCommand("forwarddelete")) in <p><a href="about:blank"><b>[z]abc</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link containing <b> (execCommand("forwarddelete")) in <p><a href="about:blank"><b>abc[d]</b></a></p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>abc</b></a></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link containing <b> (execCommand("forwarddelete")) in <p><a href="about:blank"><b>ab[cd</b></a>de]f</p>
+  assert_in_array: value "<p>YX<a href=\"about:blank\"><b>ab</b></a>f</p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XY</b>f</p>", "<p><b><a href=\"about:blank\">ab</a>XY</b>f<br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link containing <b> (execCommand("forwarddelete")) in <p>a[bc<a href="about:blank"><b>de]f</b></a></p>
+  assert_in_array: value "<p>YXa<a href=\"about:blank\"><b>f</b></a></p>" not in array ["<p>aXY<a href=\"about:blank\"><b>f</b></a></p>", "<p>aXY<a href=\"about:blank\"><b>f</b></a><br></p>"]
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_parent=b-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_parent=b-expected.txt
new file mode 100644
index 0000000..0e08db5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_parent=b-expected.txt
@@ -0,0 +1,43 @@
+This is a testharness.js-based test.
+[PASS] Testing inserting content at non-collapsed selection around link element
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (Direct typing) in <p><b><a href="about:blank">[z]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">zabc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">XYabc</a></b></p>", "<p><b><a href=\"about:blank\">XYabc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> (Direct typing) in <p><b><a href="about:blank">abc[d]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abcd</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abcXY</a></b></p>", "<p><b><a href=\"about:blank\">abcXY</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> (Direct typing) in <p><b><a href="about:blank">ab[cd</a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abcd</a>def</b></p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XYf</b></p>", "<p><b><a href=\"about:blank\">ab</a>XYf</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> (Direct typing) in <p><b>a[bc<a href="about:blank">de]f</a></b></p>
+  assert_in_array: value "<p><b>YXabc<a href=\"about:blank\">def</a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\">f</a></b></p>", "<p><b>aXY<a href=\"about:blank\">f</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (Backspace) in <p><b><a href="about:blank">[z]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">zabc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> (Backspace) in <p><b><a href="about:blank">abc[d]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abcd</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> (Backspace) in <p><b><a href="about:blank">ab[cd</a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abcd</a>def</b></p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XYf</b></p>", "<p><b><a href=\"about:blank\">ab</a>XYf</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> (Backspace) in <p><b>a[bc<a href="about:blank">de]f</a></b></p>
+  assert_in_array: value "<p><b>YXabc<a href=\"about:blank\">def</a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\">f</a></b></p>", "<p><b>aXY<a href=\"about:blank\">f</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (Delete) in <p><b><a href="about:blank">[z]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> (Delete) in <p><b><a href="about:blank">abc[d]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">bcd</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> (Delete) in <p><b><a href="about:blank">ab[cd</a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">bcd</a>def</b></p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XYf</b></p>", "<p><b><a href=\"about:blank\">ab</a>XYf</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> (Delete) in <p><b>a[bc<a href="about:blank">de]f</a></b></p>
+  assert_in_array: value "<p><b>YXbc<a href=\"about:blank\">def</a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\">f</a></b></p>", "<p><b>aXY<a href=\"about:blank\">f</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">[z]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">abc[d]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> (execCommand("delete")) in <p><b><a href="about:blank">ab[cd</a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">ab</a>f</b></p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XYf</b></p>", "<p><b><a href=\"about:blank\">ab</a>XYf</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> (execCommand("delete")) in <p><b>a[bc<a href="about:blank">de]f</a></b></p>
+  assert_in_array: value "<p><b>YXa<a href=\"about:blank\">f</a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\">f</a></b></p>", "<p><b>aXY<a href=\"about:blank\">f</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> (execCommand("forwarddelete")) in <p><b><a href="about:blank">[z]abc</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b>XY<a href=\"about:blank\">abc</a></b></p>", "<p><b>XY<a href=\"about:blank\">abc</a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> (execCommand("forwarddelete")) in <p><b><a href="about:blank">abc[d]</a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">abc</a></b></p>" not in array ["<p><b><a href=\"about:blank\">abc</a>XY</b></p>", "<p><b><a href=\"about:blank\">abc</a>XY</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> (execCommand("forwarddelete")) in <p><b><a href="about:blank">ab[cd</a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\">ab</a>f</b></p>" not in array ["<p><b><a href=\"about:blank\">ab</a>XYf</b></p>", "<p><b><a href=\"about:blank\">ab</a>XYf</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> (execCommand("forwarddelete")) in <p><b>a[bc<a href="about:blank">de]f</a></b></p>
+  assert_in_array: value "<p><b>YXa<a href=\"about:blank\">f</a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\">f</a></b></p>", "<p><b>aXY<a href=\"about:blank\">f</a></b><br></p>"]
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_parent=b_child=i-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_parent=b_child=i-expected.txt
new file mode 100644
index 0000000..d7a4645
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/editing/other/typing-around-link-element-at-non-collapsed-selection.tentative_target=DesignMode_parent=b_child=i-expected.txt
@@ -0,0 +1,43 @@
+This is a testharness.js-based test.
+[PASS] Testing inserting content at non-collapsed selection around link element
+[FAIL] Inserting "XY" after deleting first character of a link in <b> and containing <i> (Direct typing) in <p><b><a href="about:blank"><i>[z]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>zabc</i></a></b></p>" not in array ["<p><b><a href=\"about:blank\"><i>XYabc</i></a></b></p>", "<p><b><a href=\"about:blank\"><i>XYabc</i></a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> and containing <i> (Direct typing) in <p><b><a href="about:blank"><i>abc[d]</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abcd</i></a></b></p>" not in array ["<p><b><a href=\"about:blank\"><i>abcXY</i></a></b></p>", "<p><b><a href=\"about:blank\"><i>abcXY</i></a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> and containing <i> (Direct typing) in <p><b><a href="about:blank"><i>ab[cd</i></a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abcd</i></a>def</b></p>" not in array ["<p><b><i><a href=\"about:blank\">ab</a>XY</i>f</b></p>", "<p><b><i><a href=\"about:blank\">ab</a>XY</i>f</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> and containing <i> (Direct typing) in <p><b>a[bc<a href="about:blank"><i>de]f</i></a></b></p>
+  assert_in_array: value "<p><b>YXabc<a href=\"about:blank\"><i>def</i></a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\"><i>f</i></a></b></p>", "<p><b>aXY<a href=\"about:blank\"><i>f</i></a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> and containing <i> (Backspace) in <p><b><a href="about:blank"><i>[z]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>zabc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> and containing <i> (Backspace) in <p><b><a href="about:blank"><i>abc[d]</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abcd</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> and containing <i> (Backspace) in <p><b><a href="about:blank"><i>ab[cd</i></a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abcd</i></a>def</b></p>" not in array ["<p><b><i><a href=\"about:blank\">ab</a>XY</i>f</b></p>", "<p><b><i><a href=\"about:blank\">ab</a>XY</i>f</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> and containing <i> (Backspace) in <p><b>a[bc<a href="about:blank"><i>de]f</i></a></b></p>
+  assert_in_array: value "<p><b>YXabc<a href=\"about:blank\"><i>def</i></a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\"><i>f</i></a></b></p>", "<p><b>aXY<a href=\"about:blank\"><i>f</i></a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> and containing <i> (Delete) in <p><b><a href="about:blank"><i>[z]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> and containing <i> (Delete) in <p><b><a href="about:blank"><i>abc[d]</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>bcd</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> and containing <i> (Delete) in <p><b><a href="about:blank"><i>ab[cd</i></a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>bcd</i></a>def</b></p>" not in array ["<p><b><i><a href=\"about:blank\">ab</a>XY</i>f</b></p>", "<p><b><i><a href=\"about:blank\">ab</a>XY</i>f</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> and containing <i> (Delete) in <p><b>a[bc<a href="about:blank"><i>de]f</i></a></b></p>
+  assert_in_array: value "<p><b>YXbc<a href=\"about:blank\"><i>def</i></a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\"><i>f</i></a></b></p>", "<p><b>aXY<a href=\"about:blank\"><i>f</i></a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> and containing <i> (execCommand("delete")) in <p><b><a href="about:blank"><i>[z]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> and containing <i> (execCommand("delete")) in <p><b><a href="about:blank"><i>abc[d]</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> and containing <i> (execCommand("delete")) in <p><b><a href="about:blank"><i>ab[cd</i></a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>ab</i></a>f</b></p>" not in array ["<p><b><i><a href=\"about:blank\">ab</a>XY</i>f</b></p>", "<p><b><i><a href=\"about:blank\">ab</a>XY</i>f</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> and containing <i> (execCommand("delete")) in <p><b>a[bc<a href="about:blank"><i>de]f</i></a></b></p>
+  assert_in_array: value "<p><b>YXa<a href=\"about:blank\"><i>f</i></a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\"><i>f</i></a></b></p>", "<p><b>aXY<a href=\"about:blank\"><i>f</i></a></b><br></p>"]
+[FAIL] Inserting "XY" after deleting first character of a link in <b> and containing <i> (execCommand("forwarddelete")) in <p><b><a href="about:blank"><i>[z]abc</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i>XY<a href=\"about:blank\">abc</a></i></b></p>", "<p><b><i>XY<a href=\"about:blank\">abc</a></i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting last character in a non-collapsed range of a link in <b> and containing <i> (execCommand("forwarddelete")) in <p><b><a href="about:blank"><i>abc[d]</i></a></b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>abc</i></a></b></p>" not in array ["<p><b><i><a href=\"about:blank\">abc</a>XY</i></b></p>", "<p><b><i><a href=\"about:blank\">abc</a>XY</i></b><br></p>"]
+[FAIL] Inserting "XY" after deleting text after middle of a link in <b> and containing <i> (execCommand("forwarddelete")) in <p><b><a href="about:blank"><i>ab[cd</i></a>de]f</b></p>
+  assert_in_array: value "<p><b>YX<a href=\"about:blank\"><i>ab</i></a>f</b></p>" not in array ["<p><b><i><a href=\"about:blank\">ab</a>XY</i>f</b></p>", "<p><b><i><a href=\"about:blank\">ab</a>XY</i>f</b><br></p>"]
+[FAIL] Inserting "XY" after deleting text before middle of a link in <b> and containing <i> (execCommand("forwarddelete")) in <p><b>a[bc<a href="about:blank"><i>de]f</i></a></b></p>
+  assert_in_array: value "<p><b>YXa<a href=\"about:blank\"><i>f</i></a></b></p>" not in array ["<p><b>aXY<a href=\"about:blank\"><i>f</i></a></b></p>", "<p><b>aXY<a href=\"about:blank\"><i>f</i></a></b><br></p>"]
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/eventsource/request-credentials.window.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/eventsource/request-credentials.window.any.worker-expected.txt
new file mode 100644
index 0000000..1d2bffcf
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/eventsource/request-credentials.window.any.worker-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = javascript error: window.__wptrunner_process_next_event is not a function\nJavaScript stack:\nTypeError: window.__wptrunner_process_next_event is not a function\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:7:8)\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:9:4)\n    at executeAsyncScript (<anonymous>:447:47)\n    at <anonymous>:462:29\n    at callFunction (<anonymous>:341:22)\n    at <anonymous>:355:23\n    at <anonymous>:356:3\n  (Session info: chrome-headless-shell=121.0.6106.0)\nTraceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 596, in do_testharness\n    result = protocol.base.execute_script(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 56, in execute_script\n    return method(script)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 735, in execute_async_script\n    return self.send_session_command("POST", "execute/async", body)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 567, in send_command\n    raise err\nwebdriver.error.JavascriptErrorException: javascript error (500): javascript error: window.__wptrunner_process_next_event is not a function\nJavaScript stack:\nTypeError: window.__wptrunner_process_next_event is not a function\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:7:8)\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:9:4)\n    at executeAsyncScript (<anonymous>:447:47)\n    at <anonymous>:462:29\n    at callFunction (<anonymous>:341:22)\n    at <anonymous>:355:23\n    at <anonymous>:356:3\n  (Session info: chrome-headless-shell=121.0.6106.0)\n\nRemote-end stacktrace:\n\n#0 0x55bcd13c2482 <unknown>\n#1 0x55bcd13b3e03 <unknown>\n#2 0x55bcd10787c9 <unknown>\n#3 0x55bcd107ea08 <unknown>\n#4 0x55bcd107e4e6 <unknown>\n#5 0x55bcd10ed1c8 <unknown>\n#6 0x55bcd10d4da2 <unknown>\n#7 0x55bcd10aec2f <unknown>\n#8 0x55bcd10ec430 <unknown>\n#9 0x55bcd10d4a03 <unknown>\n#10 0x55bcd10ad501 <unknown>\n#11 0x55bcd10acd14 <unknown>\n#12 0x55bcd10ae17c <unknown>\n#13 0x55bcd136ea2a <unknown>\n#14 0x55bcd138774c <unknown>\n#15 0x55bcd138716b <unknown>\n#16 0x55bcd1387bf5 <unknown>\n#17 0x55bcd137816f <unknown>\n#18 0x55bcd13880e9 <unknown>\n#19 0x55bcd1360bea <unknown>\n#20 0x55bcd13a39a8 <unknown>\n#21 0x55bcd13a3b3a <unknown>\n#22 0x55bcd13b30d6 <unknown>\n#23 0x7fe2aae94ac3 <unknown>\n#24 0x7fe2aaf26a40 <unknown>\n\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/eventsource/request-redirect.window.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/eventsource/request-redirect.window.any-expected.txt
new file mode 100644
index 0000000..4a387b78
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/eventsource/request-redirect.window.any-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = javascript error: window.__wptrunner_process_next_event is not a function\nJavaScript stack:\nTypeError: window.__wptrunner_process_next_event is not a function\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:7:8)\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:9:4)\n    at executeAsyncScript (<anonymous>:447:47)\n    at <anonymous>:462:29\n    at callFunction (<anonymous>:341:22)\n    at <anonymous>:355:23\n    at <anonymous>:356:3\n  (Session info: chrome-headless-shell=121.0.6106.0)\nTraceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 596, in do_testharness\n    result = protocol.base.execute_script(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 56, in execute_script\n    return method(script)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 735, in execute_async_script\n    return self.send_session_command("POST", "execute/async", body)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 567, in send_command\n    raise err\nwebdriver.error.JavascriptErrorException: javascript error (500): javascript error: window.__wptrunner_process_next_event is not a function\nJavaScript stack:\nTypeError: window.__wptrunner_process_next_event is not a function\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:7:8)\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:9:4)\n    at executeAsyncScript (<anonymous>:447:47)\n    at <anonymous>:462:29\n    at callFunction (<anonymous>:341:22)\n    at <anonymous>:355:23\n    at <anonymous>:356:3\n  (Session info: chrome-headless-shell=121.0.6106.0)\n\nRemote-end stacktrace:\n\n#0 0x55d268151482 <unknown>\n#1 0x55d268142e03 <unknown>\n#2 0x55d267e077c9 <unknown>\n#3 0x55d267e0da08 <unknown>\n#4 0x55d267e0d4e6 <unknown>\n#5 0x55d267e7c1c8 <unknown>\n#6 0x55d267e63da2 <unknown>\n#7 0x55d267e3dc2f <unknown>\n#8 0x55d267e7b430 <unknown>\n#9 0x55d267e63a03 <unknown>\n#10 0x55d267e3c501 <unknown>\n#11 0x55d267e3bd14 <unknown>\n#12 0x55d267e3d17c <unknown>\n#13 0x55d2680fda2a <unknown>\n#14 0x55d26811674c <unknown>\n#15 0x55d26811616b <unknown>\n#16 0x55d268116bf5 <unknown>\n#17 0x55d26810716f <unknown>\n#18 0x55d2681170e9 <unknown>\n#19 0x55d2680efbea <unknown>\n#20 0x55d2681329a8 <unknown>\n#21 0x55d268132b3a <unknown>\n#22 0x55d2681420d6 <unknown>\n#23 0x7fa9e2894ac3 <unknown>\n#24 0x7fa9e2926a40 <unknown>\n\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/eventsource/request-redirect.window.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/eventsource/request-redirect.window.any.worker-expected.txt
new file mode 100644
index 0000000..1837cb90
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/eventsource/request-redirect.window.any.worker-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = javascript error: window.__wptrunner_process_next_event is not a function\nJavaScript stack:\nTypeError: window.__wptrunner_process_next_event is not a function\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:7:8)\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:9:4)\n    at executeAsyncScript (<anonymous>:447:47)\n    at <anonymous>:462:29\n    at callFunction (<anonymous>:341:22)\n    at <anonymous>:355:23\n    at <anonymous>:356:3\n  (Session info: chrome-headless-shell=121.0.6106.0)\nTraceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 596, in do_testharness\n    result = protocol.base.execute_script(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 56, in execute_script\n    return method(script)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 735, in execute_async_script\n    return self.send_session_command("POST", "execute/async", body)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 567, in send_command\n    raise err\nwebdriver.error.JavascriptErrorException: javascript error (500): javascript error: window.__wptrunner_process_next_event is not a function\nJavaScript stack:\nTypeError: window.__wptrunner_process_next_event is not a function\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:7:8)\n    at eval (eval at executeAsyncScript (:447:26), <anonymous>:9:4)\n    at executeAsyncScript (<anonymous>:447:47)\n    at <anonymous>:462:29\n    at callFunction (<anonymous>:341:22)\n    at <anonymous>:355:23\n    at <anonymous>:356:3\n  (Session info: chrome-headless-shell=121.0.6106.0)\n\nRemote-end stacktrace:\n\n#0 0x559fb4436482 <unknown>\n#1 0x559fb4427e03 <unknown>\n#2 0x559fb40ec7c9 <unknown>\n#3 0x559fb40f2a08 <unknown>\n#4 0x559fb40f24e6 <unknown>\n#5 0x559fb41611c8 <unknown>\n#6 0x559fb4148da2 <unknown>\n#7 0x559fb4122c2f <unknown>\n#8 0x559fb4160430 <unknown>\n#9 0x559fb4148a03 <unknown>\n#10 0x559fb4121501 <unknown>\n#11 0x559fb4120d14 <unknown>\n#12 0x559fb412217c <unknown>\n#13 0x559fb43e2a2a <unknown>\n#14 0x559fb43fb74c <unknown>\n#15 0x559fb43fb16b <unknown>\n#16 0x559fb43fbbf5 <unknown>\n#17 0x559fb43ec16f <unknown>\n#18 0x559fb43fc0e9 <unknown>\n#19 0x559fb43d4bea <unknown>\n#20 0x559fb44179a8 <unknown>\n#21 0x559fb4417b3a <unknown>\n#22 0x559fb44270d6 <unknown>\n#23 0x7fdc23e94ac3 <unknown>\n#24 0x7fdc23f26a40 <unknown>\n\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any-expected.txt
new file mode 100644
index 0000000..4222efc7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Request through fetch should have 'accept' header with value '*/*'
+[PASS] Request through fetch should have 'accept' header with value 'custom/*'
+[FAIL] Request through fetch should have a 'accept-language' header
+  assert_true: expected true got false
+[PASS] Request through fetch should have 'accept-language' header with value 'bzh'
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any.serviceworker-expected.txt
new file mode 100644
index 0000000..4222efc7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any.serviceworker-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Request through fetch should have 'accept' header with value '*/*'
+[PASS] Request through fetch should have 'accept' header with value 'custom/*'
+[FAIL] Request through fetch should have a 'accept-language' header
+  assert_true: expected true got false
+[PASS] Request through fetch should have 'accept-language' header with value 'bzh'
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any.sharedworker-expected.txt
new file mode 100644
index 0000000..4222efc7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any.sharedworker-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Request through fetch should have 'accept' header with value '*/*'
+[PASS] Request through fetch should have 'accept' header with value 'custom/*'
+[FAIL] Request through fetch should have a 'accept-language' header
+  assert_true: expected true got false
+[PASS] Request through fetch should have 'accept-language' header with value 'bzh'
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any.worker-expected.txt
new file mode 100644
index 0000000..4222efc7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/accept-header.any.worker-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Request through fetch should have 'accept' header with value '*/*'
+[PASS] Request through fetch should have 'accept' header with value 'custom/*'
+[FAIL] Request through fetch should have a 'accept-language' header
+  assert_true: expected true got false
+[PASS] Request through fetch should have 'accept-language' header with value 'bzh'
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/keepalive.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/keepalive.any-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/basic/keepalive.any-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/cors/cors-keepalive.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/cors/cors-keepalive.any-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/cors/cors-keepalive.any-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/redirect/redirect-keepalive.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/redirect/redirect-keepalive.any-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/api/redirect/redirect-keepalive.any-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/corb/response_block.tentative.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/corb/response_block.tentative.https-expected.txt
new file mode 100644
index 0000000..84cef9f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/corb/response_block.tentative.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] ORB: Expect error response from <script> fetch.
+  assert_equals: expected "ORB-style network error" but got "Resource loaded (expected for CORB)"
+[FAIL] ORB: Expect error response from fetch().
+  assert_equals: expected "ORB-style network error" but got "Resource loaded (expected for CORB)"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/activate-after.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/activate-after.tentative.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/activate-after.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/basic.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/basic.tentative.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/basic.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/iframe.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/iframe.tentative.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/iframe.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/new-window.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/new-window.tentative.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/new-window.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/non-secure.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/non-secure.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/non-secure.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/policies/csp-allowed.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/policies/csp-allowed.tentative.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/policies/csp-allowed.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/policies/csp-blocked.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/policies/csp-blocked.tentative.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/policies/csp-blocked.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/quota.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/quota.tentative.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/quota.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/send-on-deactivate.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/send-on-deactivate.tentative.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/fetch-later/send-on-deactivate.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any-expected.txt
new file mode 100644
index 0000000..b5eea6ba
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[FAIL] Fetching a resource from the same origin, but spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+[FAIL] Fetching a resource from the same site, but spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+[FAIL] Fetching a resource from a cross-site host, spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any.serviceworker-expected.txt
new file mode 100644
index 0000000..b5eea6ba
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any.serviceworker-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[FAIL] Fetching a resource from the same origin, but spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+[FAIL] Fetching a resource from the same site, but spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+[FAIL] Fetching a resource from a cross-site host, spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any.sharedworker-expected.txt
new file mode 100644
index 0000000..b5eea6ba
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any.sharedworker-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[FAIL] Fetching a resource from the same origin, but spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+[FAIL] Fetching a resource from the same site, but spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+[FAIL] Fetching a resource from a cross-site host, spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any.worker-expected.txt
new file mode 100644
index 0000000..b5eea6ba
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/metadata/trailing-dot.https.sub.any.worker-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[FAIL] Fetching a resource from the same origin, but spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+[FAIL] Fetching a resource from the same site, but spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+[FAIL] Fetching a resource from a cross-site host, spelled with a trailing dot.
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/orb/tentative/known-mime-type.sub.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/orb/tentative/known-mime-type.sub.any-expected.txt
new file mode 100644
index 0000000..582ab01
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/orb/tentative/known-mime-type.sub.any-expected.txt
@@ -0,0 +1,52 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Script error.
+[FAIL] ORB should block opaque font/ttf: fetch(..., {mode: "no-cors"})
+  assert_unreached: Should have rejected: fetch(..., {mode: "no-cors"}) Reached unreachable code
+[PASS] ORB should block opaque font/ttf: <img src=...>
+[PASS] ORB should block opaque font/ttf: <audio src=...>
+[PASS] ORB should block opaque font/ttf: <video src=...>
+[FAIL] ORB should block opaque font/ttf: <script src=...>
+  assert_unreached: Should have rejected: <script src=...> Reached unreachable code
+[FAIL] ORB should block opaque text/plain: fetch(..., {mode: "no-cors"})
+  assert_unreached: Should have rejected: fetch(..., {mode: "no-cors"}) Reached unreachable code
+[PASS] ORB should block opaque text/plain: <img src=...>
+[PASS] ORB should block opaque text/plain: <audio src=...>
+[PASS] ORB should block opaque text/plain: <video src=...>
+[FAIL] ORB should block opaque text/plain: <script src=...>
+  assert_unreached: Should have rejected: <script src=...> Reached unreachable code
+[FAIL] ORB should block opaque application/json (non-empty): fetch(..., {mode: "no-cors"})
+  assert_unreached: Should have rejected: fetch(..., {mode: "no-cors"}) Reached unreachable code
+[PASS] ORB should block opaque application/json (non-empty): <img src=...>
+[PASS] ORB should block opaque application/json (non-empty): <audio src=...>
+[PASS] ORB should block opaque application/json (non-empty): <video src=...>
+[FAIL] ORB should block opaque application/json (non-empty): <script src=...>
+  assert_unreached: Should have rejected: <script src=...> Reached unreachable code
+[FAIL] ORB should block opaque application/json (empty): fetch(..., {mode: "no-cors"})
+  assert_unreached: Should have rejected: fetch(..., {mode: "no-cors"}) Reached unreachable code
+[PASS] ORB should block opaque application/json (empty): <img src=...>
+[PASS] ORB should block opaque application/json (empty): <audio src=...>
+[PASS] ORB should block opaque application/json (empty): <video src=...>
+[FAIL] ORB should block opaque application/json (empty): <script src=...>
+  assert_unreached: Should have rejected: <script src=...> Reached unreachable code
+[FAIL] ORB should block opaque application/json which contains non ascii characters: fetch(..., {mode: "no-cors"})
+  assert_unreached: Should have rejected: fetch(..., {mode: "no-cors"}) Reached unreachable code
+[PASS] ORB should block opaque application/json which contains non ascii characters: <img src=...>
+[PASS] ORB should block opaque application/json which contains non ascii characters: <audio src=...>
+[PASS] ORB should block opaque application/json which contains non ascii characters: <video src=...>
+[FAIL] ORB should block opaque application/json which contains non ascii characters: <script src=...>
+  assert_unreached: Should have rejected: <script src=...> Reached unreachable code
+[PASS] ORB shouldn't block opaque image/png: fetch(..., {mode: "no-cors"})
+[PASS] ORB shouldn't block opaque image/png: <img src=...>
+[PASS] ORB shouldn't block opaque text/javascript: fetch(..., {mode: "no-cors"})
+[PASS] ORB shouldn't block opaque text/javascript: <script src=...>
+[PASS] ORB shouldn't block opaque text/javascript (utf16 encoded with BOM): fetch(..., {mode: "no-cors"})
+[PASS] ORB shouldn't block opaque text/javascript (utf16 encoded with BOM): <script src=...>
+[PASS] ORB shouldn't block opaque text/javascript (utf16 encoded without BOM but charset is provided in content-type): fetch(..., {mode: "no-cors"})
+[PASS] ORB shouldn't block opaque text/javascript (utf16 encoded without BOM but charset is provided in content-type): <script src=...>
+[PASS] ORB shouldn't block opaque text/javascript (iso-8559-1 encoded): fetch(..., {mode: "no-cors"})
+[PASS] ORB shouldn't block opaque text/javascript (iso-8559-1 encoded): <script src=...>
+[PASS] ORB shouldn't block text/javascript with valid asm.js: fetch(..., {mode: "no-cors"})
+[PASS] ORB shouldn't block text/javascript with valid asm.js: <script src=...>
+[PASS] ORB shouldn't block text/javascript with invalid asm.js: fetch(..., {mode: "no-cors"})
+[PASS] ORB shouldn't block text/javascript with invalid asm.js: <script src=...>
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/orb/tentative/nosniff.sub.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/orb/tentative/nosniff.sub.any-expected.txt
new file mode 100644
index 0000000..d2fb768d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/orb/tentative/nosniff.sub.any-expected.txt
@@ -0,0 +1,25 @@
+This is a testharness.js-based test.
+[FAIL] ORB should block opaque text/plain with nosniff: fetch(..., {mode: "no-cors"})
+  assert_unreached: Should have rejected: fetch(..., {mode: "no-cors"}) Reached unreachable code
+[PASS] ORB should block opaque text/plain with nosniff: <img src=...>
+[PASS] ORB should block opaque text/plain with nosniff: <audio src=...>
+[PASS] ORB should block opaque text/plain with nosniff: <video src=...>
+[FAIL] ORB should block opaque text/plain with nosniff: <script src=...>
+  assert_unreached: Should have rejected: <script src=...> Reached unreachable code
+[FAIL] ORB should block opaque-response-blocklisted MIME type with nosniff: fetch(..., {mode: "no-cors"})
+  assert_unreached: Should have rejected: fetch(..., {mode: "no-cors"}) Reached unreachable code
+[PASS] ORB should block opaque-response-blocklisted MIME type with nosniff: <img src=...>
+[PASS] ORB should block opaque-response-blocklisted MIME type with nosniff: <audio src=...>
+[PASS] ORB should block opaque-response-blocklisted MIME type with nosniff: <video src=...>
+[FAIL] ORB should block opaque-response-blocklisted MIME type with nosniff: <script src=...>
+  assert_unreached: Should have rejected: <script src=...> Reached unreachable code
+[FAIL] ORB should block opaque response with empty Content-Type and nosniff: fetch(..., {mode: "no-cors"})
+  assert_unreached: Should have rejected: fetch(..., {mode: "no-cors"}) Reached unreachable code
+[PASS] ORB should block opaque response with empty Content-Type and nosniff: <img src=...>
+[PASS] ORB should block opaque response with empty Content-Type and nosniff: <audio src=...>
+[PASS] ORB should block opaque response with empty Content-Type and nosniff: <video src=...>
+[FAIL] ORB should block opaque response with empty Content-Type and nosniff: <script src=...>
+  assert_unreached: Should have rejected: <script src=...> Reached unreachable code
+[PASS] ORB shouldn't block opaque image with empty Content-Type and nosniff: fetch(..., {mode: "no-cors"})
+[PASS] ORB shouldn't block opaque image with empty Content-Type and nosniff: <img src=...>
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/orb/tentative/status.sub.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/orb/tentative/status.sub.any-expected.txt
new file mode 100644
index 0000000..363aa81
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/orb/tentative/status.sub.any-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+[FAIL] ORB should block opaque-response-blocklisted MIME type with status 206: fetch(..., {mode: "no-cors"})
+  assert_unreached: Should have rejected: fetch(..., {mode: "no-cors"}) Reached unreachable code
+[PASS] ORB should block opaque-response-blocklisted MIME type with status 206: <img src=...>
+[PASS] ORB should block opaque-response-blocklisted MIME type with status 206: <audio src=...>
+[PASS] ORB should block opaque-response-blocklisted MIME type with status 206: <video src=...>
+[FAIL] ORB should block opaque-response-blocklisted MIME type with status 206: <script src=...>
+  assert_unreached: Should have rejected: <script src=...> Reached unreachable code
+[FAIL] ORB should block opaque response with non-ok status: fetch(..., {mode: "no-cors"})
+  assert_unreached: Should have rejected: fetch(..., {mode: "no-cors"}) Reached unreachable code
+[PASS] ORB should block opaque response with non-ok status: <img src=...>
+[PASS] ORB should block opaque response with non-ok status: <audio src=...>
+[PASS] ORB should block opaque response with non-ok status: <video src=...>
+[FAIL] ORB should block opaque response with non-ok status: <script src=...>
+  assert_unreached: Should have rejected: <script src=...> Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/fetch-sw.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/fetch-sw.https-expected.txt
new file mode 100644
index 0000000..3cd2d2f0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/fetch-sw.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Second fetch returns same response
+  assert_equals: expected "vfuoexberllddzyszzdg" but got "axeuxcjvyvryyxnddemj"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/fetch.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/fetch.any-expected.txt
new file mode 100644
index 0000000..6b80e686e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/fetch.any-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Second fetch returns same response
+  assert_equals: expected "crclfdfiqtvkkarrxdvp" but got "bgcpdnfbfqzcvdznswhc"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/fetch.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/fetch.any.sharedworker-expected.txt
new file mode 100644
index 0000000..2688bf8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/fetch.any.sharedworker-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Second fetch returns same response
+  assert_equals: expected "ielxkyhfptrxwhzjbtap" but got "hipqbmwrlskkazdrrbsv"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/stale-css-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/stale-css-expected.txt
new file mode 100644
index 0000000..768e461d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/stale-css-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Cache returns stale resource
+  assert_equals: (revalidated version loaded) expected "rgb(255, 0, 0)" but got "rgb(0, 128, 0)"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/stale-image-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/stale-image-expected.txt
new file mode 100644
index 0000000..16d54ea
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/stale-image-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Cache returns stale resource
+  assert_equals: (revalidated version loaded) expected 256 but got 16
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/stale-script-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/stale-script-expected.txt
new file mode 100644
index 0000000..ba5c730e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/fetch/stale-while-revalidate/stale-script-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Cache returns stale resource
+  assert_equals: (revalidated version loaded) expected 2 but got 1
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/font_access_permission.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/font_access_permission.tentative.https.window-expected.txt
new file mode 100644
index 0000000..b10d34b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/font_access_permission.tentative.https.window-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] queryLocalFonts(): permission not given
+  promise_test: Unhandled rejection with value: object "SecurityError: User activation is required."
+[PASS] queryLocalFonts(): permission denied
+[PASS] queryLocalFonts(): permission granted
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/font_access_query_select.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/font_access_query_select.tentative.https.window-expected.txt
new file mode 100644
index 0000000..11f021eb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/font_access_query_select.tentative.https.window-expected.txt
@@ -0,0 +1,18 @@
+This is a testharness.js-based test.
+[FAIL] font_access_query_select
+  assert_equals: The result length should match the test length. expected 1 but got 0
+[PASS] font_access_query_select 1
+[PASS] font_access_query_select 2
+[PASS] font_access_query_select 3
+[PASS] font_access_query_select 4
+[PASS] font_access_query_select 5
+[PASS] font_access_query_select 6
+[PASS] font_access_query_select 7
+[PASS] font_access_query_select 8
+[PASS] font_access_query_select 9
+[PASS] font_access_query_select 10
+[PASS] font_access_query_select 11
+[PASS] font_access_query_select 12
+[PASS] font_access_query_select 13
+[PASS] font_access_query_select 14
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub-expected.txt
new file mode 100644
index 0000000..974ec9a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] permissions policy allow="local-fonts" allows same-origin navigation in an iframe.
+  assert_true: local-fonts expected true got false
+[PASS] permissions policy allow="local-fonts" disallows cross-origin navigation in an iframe.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute.https.sub-expected.txt
new file mode 100644
index 0000000..3d204cea
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy-attribute.https.sub-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] permissions policy "local-fonts" can be enabled in same-origin iframe using allow="local-fonts" attribute
+  assert_true: local-fonts expected true got false
+[FAIL] permissions policy "local-fonts" can be enabled in cross-origin iframe using allow="local-fonts" attribute
+  assert_true: local-fonts expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy.https.sub-expected.txt
new file mode 100644
index 0000000..76c16d2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-allowed-by-permissions-policy.https.sub-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PASS] local-fonts-allowed-by-permissions-policy
+[FAIL] permissions policy header: local-fonts * allows same-origin iframes.
+  assert_true: local-fonts expected true got false
+[PASS] permissions policy header: local-fonts * disallows cross-origin iframes.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-default-permissions-policy.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-default-permissions-policy.https.sub-expected.txt
new file mode 100644
index 0000000..f992394
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/font-access/permissions-policy/local-fonts-default-permissions-policy.https.sub-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PASS] local-fonts-default-permissions-policy
+[FAIL] Default "local-fonts" permissions policy ["self"] allows same-origin iframes.
+  assert_true: local-fonts expected true got false
+[PASS] Default "local-fonts" permissions policy ["self"] disallows cross-origin iframes.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/gyroscope/Gyroscope-iframe-access.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/gyroscope/Gyroscope-iframe-access.https-expected.txt
new file mode 100644
index 0000000..727b59f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/gyroscope/Gyroscope-iframe-access.https-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[FAIL] Gyroscope: unfocused sensors in cross-origin frames are not updated
+  promise_test: Unhandled rejection with value: "NotAllowedError: Permissions to access sensor are not granted"
+[PASS] Gyroscope: sensors in same-origin frames are updated if one of the frames is focused
+[PASS] Gyroscope: losing a document's frame with an active sensor does not crash
+[PASS] Gyroscope: calling start() in a non-fully active document does not crash
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/gyroscope/Gyroscope.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/gyroscope/Gyroscope.https-expected.txt
new file mode 100644
index 0000000..104d9df
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/gyroscope/Gyroscope.https-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+[PASS] Gyroscope: Test that onerror is sent when permissions are not granted.
+[PASS] Gyroscope: Test that onerror is send when start() call has failed.
+[PASS] Gyroscope: Test that frequency is capped to allowed maximum.
+[PASS] Gyroscope: Test that frequency is capped to the maximum supported frequency.
+[PASS] Gyroscope: Test that frequency is limited to the minimum supported frequency.
+[PASS] Gyroscope: Test that sensor cannot be constructed within iframe disallowed to use feature policy.
+[PASS] Gyroscope: Test that sensor can be constructed within an iframe allowed to use feature policy.
+[PASS] Gyroscope: Test that 'onreading' is called and sensor reading is valid.
+[PASS] Gyroscope: sensor reading is correct.
+[PASS] Gyroscope: Test that readings are all mapped to expectedReadings correctly.
+[PASS] Gyroscope: sensor timestamp is updated when time passes.
+[PASS] Gyroscope: Test that sensor can be successfully created and its states are correct.
+[PASS] Gyroscope: no exception is thrown when calling start() on already started sensor.
+[PASS] Gyroscope: no exception is thrown when calling stop() on already stopped sensor.
+[PASS] Gyroscope: Test that fresh reading is fetched on start().
+[FAIL] Gyroscope: Readings are not delivered when the page has no visibility
+  assert_true: expected true got false
+[PASS] Gyroscope: frequency hint works.
+[PASS] Gyroscope: Readings delivered by shared platform sensor are immediately accessible to all sensors.
+[PASS] Gyroscope: throw 'TypeError' if frequency is invalid.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/anonymous-iframe/fenced-frame-bypass.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/anonymous-iframe/fenced-frame-bypass.tentative.https.window-expected.txt
new file mode 100644
index 0000000..1af5c0a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/anonymous-iframe/fenced-frame-bypass.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Error: assert_implements: HTMLFencedFrameElement is not supported. undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/anonymous-iframe/fenced-frame.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/anonymous-iframe/fenced-frame.tentative.https.window-expected.txt
new file mode 100644
index 0000000..1af5c0a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/anonymous-iframe/fenced-frame.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Error: assert_implements: HTMLFencedFrameElement is not supported. undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/broadcast-channel-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/broadcast-channel-expected.txt
new file mode 100644
index 0000000..29f8dc3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/broadcast-channel-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Eligibility (BroadcastChannel)
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] Eligibility (BroadcastChannel closed in the pagehide event)
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/dedicated-worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/dedicated-worker-expected.txt
new file mode 100644
index 0000000..356fa73
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/dedicated-worker-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Eligibility: dedicated workers
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/inflight-fetch-2-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/inflight-fetch-2-expected.txt
new file mode 100644
index 0000000..427054fc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/inflight-fetch-2-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Eligibility (in-flight fetch): Header and body received when in BFCache
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] Eligibility (in-flight fetch): Header received when in BFCache and body received after BFCache
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] Eligibility (in-flight fetch): Header and body received after BFCache
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/inflight-fetch-cors-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/inflight-fetch-cors-expected.txt
new file mode 100644
index 0000000..4fa09055
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/inflight-fetch-cors-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Eligibility (in-flight fetch): CORS succeeded when in BFCache
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] Eligibility (in-flight fetch): CORS failed when in BFCache
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
new file mode 100644
index 0000000..8746da1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] SameOrigin
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] SameSite
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] CrossSite
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] beforeunload
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] unload
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/focus-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/focus-expected.txt
new file mode 100644
index 0000000..686a84c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/focus-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Focus should be kept when page gets into and out of BFCache
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/pushstate.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/pushstate.https-expected.txt
new file mode 100644
index 0000000..16b1023
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/pushstate.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] back navigation to pushState()d page (in BFCache)
+  Could have been BFCached but actually wasn't
+[PASS] back navigation to pushState()d page (not in BFCache)
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-clients-matchall.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-clients-matchall.https-expected.txt
new file mode 100644
index 0000000..8e88d8d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-clients-matchall.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Clients.matchAll() should not list pages in BFCache
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-controlled-after-restore.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-controlled-after-restore.https-expected.txt
new file mode 100644
index 0000000..14a5034e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-controlled-after-restore.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Pages should remain controlled after restored from BFCache
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/storage-events-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/storage-events-expected.txt
new file mode 100644
index 0000000..d466caeb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/storage-events-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Storage events should not be fired for BFCached pages after becoming active
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/timers-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/timers-expected.txt
new file mode 100644
index 0000000..06cfa329
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/back-forward-cache/timers-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Timers should be paused when the page is in BFCache
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/history-traversal/same-url-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/history-traversal/same-url-expected.txt
new file mode 100644
index 0000000..74b7a96
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/history-traversal/same-url-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test same-URL navigation and its effects on history
+  assert_equals: expected 1 but got 2
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/redirect-to-unparseable-url-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/redirect-to-unparseable-url-expected.txt
new file mode 100644
index 0000000..a403564
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/redirect-to-unparseable-url-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Navigating to a url (A) that redirects to an unparseable URL (B), saves the URL (A) in the history entry, for later traversal
+  assert_equals: Precondition: history.length is 1 expected 1 but got 2
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/remote-context-helper-tests/navigation-bfcache.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/remote-context-helper-tests/navigation-bfcache.window-expected.txt
new file mode 100644
index 0000000..779e202
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/remote-context-helper-tests/navigation-bfcache.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] RemoteContextHelper navigation using BFCache
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'persisted')"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/unloading-documents/prompt/004-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/unloading-documents/prompt/004-expected.txt
new file mode 100644
index 0000000..ce00e179
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/browsing-the-web/unloading-documents/prompt/004-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = javascript error: document unloaded while waiting for result\n  (Session info: chrome-headless-shell=121.0.6106.0)\nTraceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 596, in do_testharness\n    result = protocol.base.execute_script(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 56, in execute_script\n    return method(script)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 735, in execute_async_script\n    return self.send_session_command("POST", "execute/async", body)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 567, in send_command\n    raise err\nwebdriver.error.JavascriptErrorException: javascript error (500): javascript error: document unloaded while waiting for result\n  (Session info: chrome-headless-shell=121.0.6106.0)\n\nRemote-end stacktrace:\n\n#0 0x559cad4b4482 <unknown>\n#1 0x559cad4a5e03 <unknown>\n#2 0x559cad16a7c9 <unknown>\n#3 0x559cad170a08 <unknown>\n#4 0x559cad1704e6 <unknown>\n#5 0x559cad1df1c8 <unknown>\n#6 0x559cad1c6da2 <unknown>\n#7 0x559cad1a0c2f <unknown>\n#8 0x559cad1de430 <unknown>\n#9 0x559cad1c6a03 <unknown>\n#10 0x559cad19f501 <unknown>\n#11 0x559cad19ed14 <unknown>\n#12 0x559cad1a017c <unknown>\n#13 0x559cad460a2a <unknown>\n#14 0x559cad47974c <unknown>\n#15 0x559cad47916b <unknown>\n#16 0x559cad479bf5 <unknown>\n#17 0x559cad46a16f <unknown>\n#18 0x559cad47a0e9 <unknown>\n#19 0x559cad452bea <unknown>\n#20 0x559cad4959a8 <unknown>\n#21 0x559cad495b3a <unknown>\n#22 0x559cad4a50d6 <unknown>\n#23 0x7fcd8b094ac3 <unknown>\n#24 0x7fcd8b126a40 <unknown>\n\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/history/the-history-interface/history-state-after-bfcache.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/history/the-history-interface/history-state-after-bfcache.window-expected.txt
new file mode 100644
index 0000000..f1a62d0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/browsers/history/the-history-interface/history-state-after-bfcache.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Navigating back to a bfcached page does not reset history.state
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'persisted')"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https-expected.txt
new file mode 100644
index 0000000..8707988
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 621, in do_testharness\n    protocol.testharness.close_old_windows()\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 93, in close_old_windows\n    for handle in self.webdriver.handles:\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 671, in handles\n    return self.send_session_command("GET", "window/handles")\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 555, in send_command\n    response = self.transport.send(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 234, in send\n    response = self._request(method, uri, payload, headers, timeout=None)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 259, in _request\n    response = self.connection.getresponse()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 1344, in getresponse\n    response.begin()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 307, in begin\n    version, status, reason = self._read_status()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 276, in _read_status\n    raise RemoteDisconnected("Remote end closed connection without"\nhttp.client.RemoteDisconnected: Remote end closed connection without response\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https-expected.txt
new file mode 100644
index 0000000..8707988
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 621, in do_testharness\n    protocol.testharness.close_old_windows()\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 93, in close_old_windows\n    for handle in self.webdriver.handles:\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 671, in handles\n    return self.send_session_command("GET", "window/handles")\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 555, in send_command\n    response = self.transport.send(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 234, in send\n    response = self._request(method, uri, payload, headers, timeout=None)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 259, in _request\n    response = self.connection.getresponse()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 1344, in getresponse\n    response.begin()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 307, in begin\n    version, status, reason = self._read_status()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 276, in _read_status\n    raise RemoteDisconnected("Remote end closed connection without"\nhttp.client.RemoteDisconnected: Remote end closed connection without response\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https-expected.txt
new file mode 100644
index 0000000..8707988
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 621, in do_testharness\n    protocol.testharness.close_old_windows()\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 93, in close_old_windows\n    for handle in self.webdriver.handles:\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 671, in handles\n    return self.send_session_command("GET", "window/handles")\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 555, in send_command\n    response = self.transport.send(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 234, in send\n    response = self._request(method, uri, payload, headers, timeout=None)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 259, in _request\n    response = self.connection.getresponse()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 1344, in getresponse\n    response.begin()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 307, in begin\n    version, status, reason = self._read_status()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 276, in _read_status\n    raise RemoteDisconnected("Remote end closed connection without"\nhttp.client.RemoteDisconnected: Remote end closed connection without response\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https-expected.txt
new file mode 100644
index 0000000..1c4f750b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = no such window: No target with given id found\n  (Session info: chrome-headless-shell=121.0.6106.0)\nTraceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 621, in do_testharness\n    protocol.testharness.close_old_windows()\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 93, in close_old_windows\n    for handle in self.webdriver.handles:\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 671, in handles\n    return self.send_session_command("GET", "window/handles")\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 567, in send_command\n    raise err\nwebdriver.error.NoSuchWindowException: no such window (404): no such window: No target with given id found\n  (Session info: chrome-headless-shell=121.0.6106.0)\n\nRemote-end stacktrace:\n\n#0 0x556d4dadd482 <unknown>\n#1 0x556d4dacee03 <unknown>\n#2 0x556d4d7937c9 <unknown>\n#3 0x556d4d7822aa <unknown>\n#4 0x556d4d7809ed <unknown>\n#5 0x556d4d780c89 <unknown>\n#6 0x556d4d794065 <unknown>\n#7 0x556d4d7740cc <unknown>\n#8 0x556d4d77443e <unknown>\n#9 0x556d4d7fc652 <unknown>\n#10 0x556d4d7efd68 <unknown>\n#11 0x556d4d7c8501 <unknown>\n#12 0x556d4d7c7d14 <unknown>\n#13 0x556d4d7c917c <unknown>\n#14 0x556d4da89a2a <unknown>\n#15 0x556d4daa274c <unknown>\n#16 0x556d4daa216b <unknown>\n#17 0x556d4daa2bf5 <unknown>\n#18 0x556d4da9316f <unknown>\n#19 0x556d4daa30e9 <unknown>\n#20 0x556d4da7bbea <unknown>\n#21 0x556d4dabe9a8 <unknown>\n#22 0x556d4dabeb3a <unknown>\n#23 0x556d4dace0d6 <unknown>\n#24 0x7f86bee94ac3 <unknown>\n#25 0x7f86bef26a40 <unknown>\n\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro.https-expected.txt
new file mode 100644
index 0000000..8707988
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 621, in do_testharness\n    protocol.testharness.close_old_windows()\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 93, in close_old_windows\n    for handle in self.webdriver.handles:\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 671, in handles\n    return self.send_session_command("GET", "window/handles")\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 555, in send_command\n    response = self.transport.send(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 234, in send\n    response = self._request(method, uri, payload, headers, timeout=None)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 259, in _request\n    response = self.connection.getresponse()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 1344, in getresponse\n    response.begin()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 307, in begin\n    version, status, reason = self._read_status()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 276, in _read_status\n    raise RemoteDisconnected("Remote end closed connection without"\nhttp.client.RemoteDisconnected: Remote end closed connection without response\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro_cross-origin.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro_cross-origin.https-expected.txt
new file mode 100644
index 0000000..bd7b38a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro_cross-origin.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] access-from-coop-page-to-openee, cross-origin
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+[FAIL] access-from-coop-page-to-openee, cross-origin + redirect
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro.https-expected.txt
new file mode 100644
index 0000000..dba2e1c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] access-from-coop-page-to-opener, same-origin
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+[FAIL] access-from-coop-page-to-opener, same-origin + redirect
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro_cross-origin.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro_cross-origin.https-expected.txt
new file mode 100644
index 0000000..1ef0ba8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-opener_coop-ro_cross-origin.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] access-from-coop-page-to-opener, cross-origin
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+[FAIL] access-from-coop-page-to-opener, cross-origin + redirect
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro.https-expected.txt
new file mode 100644
index 0000000..e92bb345
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] access-from-coop-page-to-other (COOP-RO)
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro.https-expected.txt
new file mode 100644
index 0000000..ae1e034
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] access-to-coop-page-from-openee, same-origin
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+[FAIL] access-to-coop-page-from-openee, same-origin + redirect
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro_cross-origin.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro_cross-origin.https-expected.txt
new file mode 100644
index 0000000..b48bd54
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro_cross-origin.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] access-to-coop-page-from-openee, cross-origin
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+[FAIL] access-to-coop-page-from-openee, cross-origin + redirect)
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro.https-expected.txt
new file mode 100644
index 0000000..1545ac1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] access-to-coop-page-from-opener, same-origin
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+[FAIL] access-to-coop-page-from-opener, same-origin + redirect
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-close.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-close.https-expected.txt
new file mode 100644
index 0000000..8707988
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-close.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 621, in do_testharness\n    protocol.testharness.close_old_windows()\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 93, in close_old_windows\n    for handle in self.webdriver.handles:\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 671, in handles\n    return self.send_session_command("GET", "window/handles")\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 555, in send_command\n    response = self.transport.send(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 234, in send\n    response = self._request(method, uri, payload, headers, timeout=None)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 259, in _request\n    response = self.connection.getresponse()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 1344, in getresponse\n    response.begin()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 307, in begin\n    version, status, reason = self._read_status()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 276, in _read_status\n    raise RemoteDisconnected("Remote end closed connection without"\nhttp.client.RemoteDisconnected: Remote end closed connection without response\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-closed.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-closed.https-expected.txt
new file mode 100644
index 0000000..2063e1a1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-closed.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] same-origin > w => w.closed
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+[FAIL] cross-origin > w => w.closed
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-focus.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-focus.https-expected.txt
new file mode 100644
index 0000000..6395f1c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-focus.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] same-origin > w => w.focus()
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+[FAIL] cross-origin > w => w.focus()
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-frames.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-frames.https-expected.txt
new file mode 100644
index 0000000..7a424f5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-frames.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] same-origin > w => w.frames
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+[FAIL] cross-origin > w => w.frames
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-length.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-length.https-expected.txt
new file mode 100644
index 0000000..5930943d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-length.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] same-origin > w => w.length
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+[FAIL] cross-origin > w => w.length
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-get.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-get.https-expected.txt
new file mode 100644
index 0000000..1c942a81
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-get.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] same-origin > w => w.location
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+[FAIL] cross-origin > w => w.location
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-set.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-set.https-expected.txt
new file mode 100644
index 0000000..8a6b956
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-set.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] same-origin > w => w.location = "#"
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+[FAIL] cross-origin > w => w.location = "#"
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-get.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-get.https-expected.txt
new file mode 100644
index 0000000..663cf5ba
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-get.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] same-origin > w => w.opener
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+[FAIL] cross-origin > w => w.opener
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https-expected.txt
new file mode 100644
index 0000000..8707988
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 621, in do_testharness\n    protocol.testharness.close_old_windows()\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 93, in close_old_windows\n    for handle in self.webdriver.handles:\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 671, in handles\n    return self.send_session_command("GET", "window/handles")\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 555, in send_command\n    response = self.transport.send(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 234, in send\n    response = self._request(method, uri, payload, headers, timeout=None)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 259, in _request\n    response = self.connection.getresponse()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 1344, in getresponse\n    response.begin()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 307, in begin\n    version, status, reason = self._read_status()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 276, in _read_status\n    raise RemoteDisconnected("Remote end closed connection without"\nhttp.client.RemoteDisconnected: Remote end closed connection without response\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-2.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-2.https-expected.txt
new file mode 100644
index 0000000..8707988
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-2.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 621, in do_testharness\n    protocol.testharness.close_old_windows()\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 93, in close_old_windows\n    for handle in self.webdriver.handles:\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 671, in handles\n    return self.send_session_command("GET", "window/handles")\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 555, in send_command\n    response = self.transport.send(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 234, in send\n    response = self._request(method, uri, payload, headers, timeout=None)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 259, in _request\n    response = self.connection.getresponse()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 1344, in getresponse\n    response.begin()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 307, in begin\n    version, status, reason = self._read_status()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 276, in _read_status\n    raise RemoteDisconnected("Remote end closed connection without"\nhttp.client.RemoteDisconnected: Remote end closed connection without response\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-self.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-self.https-expected.txt
new file mode 100644
index 0000000..172d927
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-self.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] same-origin > w => w.self
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+[FAIL] cross-origin > w => w.self
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-window.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-window.https-expected.txt
new file mode 100644
index 0000000..939054a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-window.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] same-origin > w => w.window
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+[FAIL] cross-origin > w => w.window
+  promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'property')"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/report-to-both_coop-ro.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/report-to-both_coop-ro.https-expected.txt
new file mode 100644
index 0000000..4559d01
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/report-to-both_coop-ro.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] Access from opener
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+[FAIL] Access from openee
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https-expected.txt
new file mode 100644
index 0000000..a0f8f00
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/report-only-four-reports.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] coop document reporting test A test with both COOP and COOP report only setup using Reporting-Endpoints header to CROSS_ORIGIN with same-origin-allow-popups; report-to="coop-popup-report-endpoint", require-corp, same-origin; report-to="coop-popup-report-only-endpoint", require-corp
+  assert_equals: has exactly one report for coop-report-endpoint expected 1 but got 0
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https-expected.txt
new file mode 100644
index 0000000..4559d01
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] Access from opener
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+[FAIL] Access from openee
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https-expected.txt
new file mode 100644
index 0000000..1c54986
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] Same origin openee redirected to same-origin with unsafe-none
+  assert_equals: expected 1 but got 0
+[FAIL] Cross origin openee redirected to same-origin with unsafe-none
+  assert_equals: expected 1 but got 0
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https-expected.txt
new file mode 100644
index 0000000..72edd6351
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] coop reporting test A test with both COOP and COOP report only setup to CROSS_ORIGIN with same-origin-allow-popups; report-to="coop-popup-report-endpoint", require-corp, same-origin; report-to="coop-popup-report-only-endpoint", require-corp
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-allow-popups\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-from-unsafe-none.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-from-unsafe-none.https-expected.txt
new file mode 100644
index 0000000..64ba5bf
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-from-unsafe-none.https-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[FAIL] coop reporting test Report only tests for an opener without any COOP/COOP report only set to SAME_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-popup-report-only-endpoint, expected report: {\"body\":{\"disposition\":\"reporting\",\"effectivePolicy\":\"same-origin\",\"previousResponseURL\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-from-unsafe-none.https.html\",\"referrer\":\"https://web-platform.test:8444/\",\"type\":\"navigation-to-response\"},\"url\":\"/uuid=(uuid)$/\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test Report only tests for an opener without any COOP/COOP report only set to CROSS_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-popup-report-only-endpoint, expected report: {\"body\":{\"disposition\":\"reporting\",\"effectivePolicy\":\"same-origin\",\"previousResponseURL\":\"\",\"referrer\":\"https://web-platform.test:8444/\",\"type\":\"navigation-to-response\"},\"url\":\"/uuid=(uuid)$/\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https-expected.txt
new file mode 100644
index 0000000..8f09a88
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with , , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-only-endpoint, expected report: {\"body\":{\"disposition\":\"reporting\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-only-endpoint, expected report: {\"body\":{\"disposition\":\"reporting\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] coop reporting test reporting same origin with report-to to SAME_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", 
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin.https-expected.txt
new file mode 100644
index 0000000..4a4824dd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin.https-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with , require-corp, same-origin; report-to="coop-popup-report-only-endpoint", 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-popup-report-only-endpoint, expected report: {\"body\":{\"disposition\":\"reporting\",\"effectivePolicy\":\"same-origin-plus-coep\",\"previousResponseURL\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin.https.html\",\"referrer\":\"https://web-platform.test:8444/\",\"type\":\"navigation-to-response\"},\"url\":\"/uuid=(uuid)$/\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", require-corp
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-popup-report-only-endpoint, expected report: {\"body\":{\"disposition\":\"reporting\",\"effectivePolicy\":\"same-origin-plus-coep\",\"previousResponseURL\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin.https.html\",\"referrer\":\"https://web-platform.test:8444/\",\"type\":\"navigation-to-response\"},\"url\":\"/uuid=(uuid)$/\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-opener.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-opener.https-expected.txt
new file mode 100644
index 0000000..60a40c7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-opener.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] navigation-report-from-opener-navigation
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https-expected.txt
new file mode 100644
index 0000000..37fee1c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Open a popup to a document without COOP, then navigate it to a document with
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-popup-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"unsafe-none\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"/uuid=(uuid)$/\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https-expected.txt
new file mode 100644
index 0000000..94c3c55
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-allow-popups\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with same-origin-allow-popups; report-to="coop-popup-report-endpoint", require-corp, , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-allow-popups\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with same-origin, require-corp, , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-allow-popups\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https-expected.txt
new file mode 100644
index 0000000..834005d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+[PASS] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", require-corp, , 
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-plus-coep\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", require-corp, , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-plus-coep\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", require-corp
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-plus-coep\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", require-corp
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-plus-coep\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https-expected.txt
new file mode 100644
index 0000000..fc5ba24
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https-expected.txt
@@ -0,0 +1,14 @@
+This is a testharness.js-based test.
+[PASS] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with unsafe-none; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", require-corp, , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with unsafe-none; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with unsafe-none, , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin.https-expected.txt
new file mode 100644
index 0000000..88fc4bf
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin.https-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+[FAIL] coop reporting test reporting same origin to CROSS_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-popup-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin\",\"previousResponseURL\":\"\",\"referrer\":\"https://web-platform.test:8444/\",\"type\":\"navigation-to-response\"},\"url\":\"/uuid=(uuid)$/\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin to SAME_ORIGIN with unsafe-none; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-popup-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"unsafe-none\",\"previousResponseURL\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin.https.html\",\"referrer\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin.https.html\",\"type\":\"navigation-to-response\"},\"url\":\"/uuid=(uuid)$/\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin to CROSS_ORIGIN with unsafe-none; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-popup-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"previousResponseURL\":\"\",\"referrer\":\"https://web-platform.test:8444/\",\"type\":\"navigation-to-response\"},\"url\":\"/uuid=(uuid)$/\",\"type\":\"coop\"}, within available reports: []"
+[PASS] coop reporting test reporting same origin to SAME_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", 
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https-expected.txt
new file mode 100644
index 0000000..1fecc42
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"unsafe-none\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin, , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"unsafe-none\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"unsafe-none\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-redirect-with-same-origin-allow-popups.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-redirect-with-same-origin-allow-popups.https-expected.txt
new file mode 100644
index 0000000..8707988
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-redirect-with-same-origin-allow-popups.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 621, in do_testharness\n    protocol.testharness.close_old_windows()\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 93, in close_old_windows\n    for handle in self.webdriver.handles:\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 671, in handles\n    return self.send_session_command("GET", "window/handles")\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 555, in send_command\n    response = self.transport.send(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 234, in send\n    response = self._request(method, uri, payload, headers, timeout=None)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 259, in _request\n    response = self.connection.getresponse()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 1344, in getresponse\n    response.begin()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 307, in begin\n    version, status, reason = self._read_status()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 276, in _read_status\n    raise RemoteDisconnected("Remote end closed connection without"\nhttp.client.RemoteDisconnected: Remote end closed connection without response\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/access-reporting-opener-rp-ro.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/access-reporting-opener-rp-ro.https-expected.txt
new file mode 100644
index 0000000..f38525d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/access-reporting-opener-rp-ro.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] access-reporting-opener-rp-ro
+  assert_equals: expected (string) "coop" but got (undefined) undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https-expected.txt
new file mode 100644
index 0000000..8707988
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 621, in do_testharness\n    protocol.testharness.close_old_windows()\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 93, in close_old_windows\n    for handle in self.webdriver.handles:\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 671, in handles\n    return self.send_session_command("GET", "window/handles")\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 555, in send_command\n    response = self.transport.send(\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 234, in send\n    response = self._request(method, uri, payload, headers, timeout=None)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py", line 259, in _request\n    response = self.connection.getresponse()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 1344, in getresponse\n    response.begin()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 307, in begin\n    version, status, reason = self._read_status()\n  File "/b/s/w/ir/.task_template_vpython_cache/vpython/store/cpython-n8umfpv0s1ufm2q1s4irhb59jc/contents/lib/python3.8/http/client.py", line 276, in _read_status\n    raise RemoteDisconnected("Remote end closed connection without"\nhttp.client.RemoteDisconnected: Remote end closed connection without response\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https-expected.txt
new file mode 100644
index 0000000..3dbedac
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = no such window: No target with given id found\n  (Session info: chrome-headless-shell=121.0.6106.0)\nTraceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 621, in do_testharness\n    protocol.testharness.close_old_windows()\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 93, in close_old_windows\n    for handle in self.webdriver.handles:\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 22, in inner\n    return func(self, *args, **kwargs)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 671, in handles\n    return self.send_session_command("GET", "window/handles")\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 603, in send_session_command\n    return self.send_command(method, url, body, timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 567, in send_command\n    raise err\nwebdriver.error.NoSuchWindowException: no such window (404): no such window: No target with given id found\n  (Session info: chrome-headless-shell=121.0.6106.0)\n\nRemote-end stacktrace:\n\n#0 0x5572c162d482 <unknown>\n#1 0x5572c161ee03 <unknown>\n#2 0x5572c12e37c9 <unknown>\n#3 0x5572c12d22aa <unknown>\n#4 0x5572c12d09ed <unknown>\n#5 0x5572c12d0c89 <unknown>\n#6 0x5572c12e4065 <unknown>\n#7 0x5572c12c40cc <unknown>\n#8 0x5572c12c443e <unknown>\n#9 0x5572c134c652 <unknown>\n#10 0x5572c133fd68 <unknown>\n#11 0x5572c1318501 <unknown>\n#12 0x5572c1317d14 <unknown>\n#13 0x5572c131917c <unknown>\n#14 0x5572c15d9a2a <unknown>\n#15 0x5572c15f274c <unknown>\n#16 0x5572c15f216b <unknown>\n#17 0x5572c15f2bf5 <unknown>\n#18 0x5572c15e316f <unknown>\n#19 0x5572c15f30e9 <unknown>\n#20 0x5572c15cbbea <unknown>\n#21 0x5572c160e9a8 <unknown>\n#22 0x5572c160eb3a <unknown>\n#23 0x5572c161e0d6 <unknown>\n#24 0x7f4fbc894ac3 <unknown>\n#25 0x7f4fbc926a40 <unknown>\n\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https-expected.txt
new file mode 100644
index 0000000..3353553
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[FAIL] SAME_ORIGIN popup with coop restrict-properties
+  assert_false: Main page has dom access to the popup? expected false got true
+[FAIL] SAME_SITE popup with coop restrict-properties
+  assert_false: Main page has cross origin access to the popup? expected false got true
+[FAIL] CROSS_ORIGIN popup with coop restrict-properties
+  assert_false: Main page has cross origin access to the popup? expected false got true
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01-expected.txt
new file mode 100644
index 0000000..ecbf026
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01-expected.txt
@@ -0,0 +1,34 @@
+This is a testharness.js-based test.
+[PASS] Should get an error event for a 404 error.
+[PASS] Should get an error event for an unsupported URL.
+[PASS] Stylesheet loading using <link> with no Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with no Content-Type, same-origin, and nosniff
+[FAIL] Stylesheet loading using <link> with wrong Content-Type, same-origin, and no nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[PASS] Stylesheet loading using <link> with wrong Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using <link> with broken Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with broken Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using <link> with no Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with no Content-Type, cross-origin, and nosniff
+[FAIL] Stylesheet loading using <link> with wrong Content-Type, cross-origin, and no nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[FAIL] Stylesheet loading using <link> with wrong Content-Type, cross-origin, and nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[PASS] Stylesheet loading using <link> with broken Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with broken Content-Type, cross-origin, and nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, same-origin, and nosniff
+[FAIL] Stylesheet loading using @import with wrong Content-Type, same-origin, and no nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[PASS] Stylesheet loading using @import with wrong Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using @import with broken Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using @import with broken Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, cross-origin, and nosniff
+[FAIL] Stylesheet loading using @import with wrong Content-Type, cross-origin, and no nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[FAIL] Stylesheet loading using @import with wrong Content-Type, cross-origin, and nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[PASS] Stylesheet loading using @import with broken Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using @import with broken Content-Type, cross-origin, and nosniff
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-limited-quirks-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-limited-quirks-expected.txt
new file mode 100644
index 0000000..524057f3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-limited-quirks-expected.txt
@@ -0,0 +1,30 @@
+This is a testharness.js-based test.
+[PASS] Stylesheet loading using <link> with no Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with no Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using <link> with wrong Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with wrong Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using <link> with broken Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with broken Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using <link> with no Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with no Content-Type, cross-origin, and nosniff
+[FAIL] Stylesheet loading using <link> with wrong Content-Type, cross-origin, and no nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[FAIL] Stylesheet loading using <link> with wrong Content-Type, cross-origin, and nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[PASS] Stylesheet loading using <link> with broken Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with broken Content-Type, cross-origin, and nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using @import with wrong Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using @import with wrong Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using @import with broken Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using @import with broken Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, cross-origin, and nosniff
+[FAIL] Stylesheet loading using @import with wrong Content-Type, cross-origin, and no nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[FAIL] Stylesheet loading using @import with wrong Content-Type, cross-origin, and nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[PASS] Stylesheet loading using @import with broken Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using @import with broken Content-Type, cross-origin, and nosniff
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-quirks-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-quirks-expected.txt
new file mode 100644
index 0000000..524057f3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/document-metadata/the-link-element/link-style-error-quirks-expected.txt
@@ -0,0 +1,30 @@
+This is a testharness.js-based test.
+[PASS] Stylesheet loading using <link> with no Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with no Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using <link> with wrong Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with wrong Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using <link> with broken Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with broken Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using <link> with no Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with no Content-Type, cross-origin, and nosniff
+[FAIL] Stylesheet loading using <link> with wrong Content-Type, cross-origin, and no nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[FAIL] Stylesheet loading using <link> with wrong Content-Type, cross-origin, and nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[PASS] Stylesheet loading using <link> with broken Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using <link> with broken Content-Type, cross-origin, and nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using @import with wrong Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using @import with wrong Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using @import with broken Content-Type, same-origin, and no nosniff
+[PASS] Stylesheet loading using @import with broken Content-Type, same-origin, and nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using @import with no Content-Type, cross-origin, and nosniff
+[FAIL] Stylesheet loading using @import with wrong Content-Type, cross-origin, and no nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[FAIL] Stylesheet loading using @import with wrong Content-Type, cross-origin, and nosniff
+  assert_unreached: error event should have fired Reached unreachable code
+[PASS] Stylesheet loading using @import with broken Content-Type, cross-origin, and no nosniff
+[PASS] Stylesheet loading using @import with broken Content-Type, cross-origin, and nosniff
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-html-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-html-expected.txt
new file mode 100644
index 0000000..39c5a6a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-html-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Page with <embed type=text/html src=/resources/blank.html>
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] Page with <object type=text/html data=/resources/blank.html>
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-img-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-img-expected.txt
new file mode 100644
index 0000000..98be4da0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-img-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Page with <embed type=image/png src=/images/blue.png>
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] Page with <object type=image/png data=/images/blue.png>
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-js-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-js-expected.txt
new file mode 100644
index 0000000..be68c1d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-js-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Page with <embed type=application/javascript src=/resources/test-only-api.js>
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] Page with <object type=application/javascript data=/resources/test-only-api.js>
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-mp4-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-mp4-expected.txt
new file mode 100644
index 0000000..882622c8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-mp4-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Page with <embed type=undefined src=/media/white.mp4>
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] Page with <object type=undefined data=/media/white.mp4>
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-not-found-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-not-found-expected.txt
new file mode 100644
index 0000000..760975f7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-not-found-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Page with <embed type=image/png src=/404.png>
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] Page with <object type=image/png data=/404.png>
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-type-only-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-type-only-expected.txt
new file mode 100644
index 0000000..a455f76
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/bfcache/embedded-type-only-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Page with <embed type=text/html src=undefined>
+  Could have been BFCached but actually wasn't
+[PRECONDITION_FAILED] Page with <object type=text/html data=undefined>
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-base-url-2-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-base-url-2-expected.txt
new file mode 100644
index 0000000..5b6ba283
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-base-url-2-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] When a loading=lazy image is loaded, it loads relative to the document's base URL computed at parse-time.
+  assert_unreached: The image request should not load relative to the current (incorrect) base URL. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-button-type-behavior.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-button-type-behavior.tentative-expected.txt
new file mode 100644
index 0000000..a9d1f2d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-button-type-behavior.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] <button type=selectlist> should open the parent selectlist when clicked.
+  promise_test: Unhandled rejection with value: "error: Action send_keys failed"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-events.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-events.tentative-expected.txt
new file mode 100644
index 0000000..b61f9633
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-events.tentative-expected.txt
@@ -0,0 +1,15 @@
+This is a testharness.js-based test.
+[PASS] Button controller code should not run if the click event is preventDefaulted.
+[PASS] Listbox controller code should not run if the click event is preventDefaulted.
+[FAIL] <selectlist> should fire input and change events when new option is selected.
+  assert_false: expected false got true
+[FAIL] <selectlist> should fire input and change events even when new selected option has the same value as the old.
+  assert_array_equals: input event should have fired after ArrowDown. lengths differ, expected array ["input"] length 1, got [] length 0
+[PASS] <selectlist> should fire input and change events when option in listbox is clicked
+[FAIL] Check that <Space> opens <selectlist>.
+  assert_false: <Enter> should close selectlist expected false got true
+[FAIL] Check that <Space> opens <selectlist> when <selectlist> specifies tabindex
+  assert_false: <Enter> should close selectlist expected false got true
+[FAIL] Test that <selectlist> button slot receives key events.
+  promise_test: Unhandled rejection with value: "error: Action send_keys failed"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-keyboard-behavior.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-keyboard-behavior.tentative-expected.txt
new file mode 100644
index 0000000..bbedafa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-keyboard-behavior.tentative-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+[PASS] defaultbutton: When the listbox is closed, spacebar should open the listbox.
+[PASS] defaultbutton: When the listbox is closed, all arrow keys should open the listbox.
+[PASS] defaultbutton: When the listbox is closed, the enter key should submit the form or do nothing.
+[PASS] defaultbutton: When the listbox is open, the enter key should commit the selected option.
+[FAIL] custombutton: When the listbox is closed, spacebar should open the listbox.
+  promise_test: Unhandled rejection with value: "error: Action send_keys failed"
+[FAIL] custombutton: When the listbox is closed, all arrow keys should open the listbox.
+  promise_test: Unhandled rejection with value: "error: Action send_keys failed"
+[PASS] custombutton: When the listbox is closed, the enter key should submit the form or do nothing.
+[PASS] custombutton: When the listbox is open, the enter key should commit the selected option.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-keyboard.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-keyboard.tentative-expected.txt
new file mode 100644
index 0000000..3b34a429
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-keyboard.tentative-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[FAIL] Validate Enter, Up/Down Arrow, and Space keyboard accessibility support for <selectlist>
+  promise_test: Unhandled rejection with value: "error: Action send_keys failed"
+[PASS] Firing a synthetic event at a selectlist's option doesn't crash
+[FAIL] Validate Enter, Up/Down Arrow keyboard accessibility support for disabled <selectlist>
+  promise_test: Unhandled rejection with value: "error: Action send_keys failed"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-option-focusable.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-option-focusable.tentative-expected.txt
new file mode 100644
index 0000000..29efb9f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-option-focusable.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Validate <option> is focusable when is a descendant of <selectlist>
+  assert_equals: expected "two" but got "one"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-pseudo-light-dismiss-invalidation.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-pseudo-light-dismiss-invalidation.tentative-expected.txt
new file mode 100644
index 0000000..c463a84
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-pseudo-light-dismiss-invalidation.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] selectlist should not match :open when light dismissed.
+  promise_test: Unhandled rejection with value: "error: Action click failed"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-tabindex-order.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-tabindex-order.tentative-expected.txt
new file mode 100644
index 0000000..9da8a34
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/forms/the-selectlist-element/selectlist-tabindex-order.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Check that tabindex applies to <selectlist>
+  assert_equals: input3 should be active expected "input3" but got ""
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-canceling-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-canceling-expected.txt
new file mode 100644
index 0000000..e0a0951
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-canceling-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Modal dialogs should close when the escape key is pressed.
+  assert_true: Input should swallow Escape mechanism. expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/interactive-elements/the-dialog-element/focus-previous-iframe.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/interactive-elements/the-dialog-element/focus-previous-iframe.tentative-expected.txt
new file mode 100644
index 0000000..93d3861
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/interactive-elements/the-dialog-element/focus-previous-iframe.tentative-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught Error: assert_equals: expected Element node <input></input> but got Element node <iframe srcdoc="<input><dialog> Dialog in child </dialog>...
+[PASS] Focus should move back from parent document to child document
+[PASS] Focus should move back from child document to parent document
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-light-dismiss-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-light-dismiss-expected.txt
new file mode 100644
index 0000000..296bd5d0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-light-dismiss-expected.txt
@@ -0,0 +1,32 @@
+This is a testharness.js-based test.
+[PASS] Clicking outside a popover will dismiss the popover
+[PASS] Canceling pointer events should not keep clicks from light dismissing popovers
+[PASS] Clicking inside a popover does not close that popover
+[PASS] Popovers close on pointerup, not pointerdown
+[PASS] Synthetic events can't close popovers
+[PASS] Moving focus outside the popover should not dismiss the popover
+[PASS] Clicking inside a child popover shouldn't close either popover
+[PASS] Clicking inside a parent popover should close child popover
+[PASS] Clicking on invoking element, after using it for activation, shouldn't close its popover
+[PASS] Clicking on invoking element, after using it for activation, shouldn't close its popover (nested case)
+[PASS] Clicking on invoking element, after using it for activation, shouldn't close its popover (nested case, not used for invocation)
+[PASS] Clicking on invoking element, even if it wasn't used for activation, shouldn't close its popover
+[PASS] Clicking on popovertarget element, even if it wasn't used for activation, should hide it exactly once
+[PASS] Dragging from an open popover outside an open popover should leave the popover open
+[PASS] A popover inside an invoking element doesn't participate in that invoker's ancestor chain
+[PASS] An invoking element that was not used to invoke the popover is not part of the ancestor chain
+[PASS] Scrolling within a popover should not close the popover
+[PASS] Clicking inside a shadow DOM popover does not close that popover
+[PASS] Clicking outside a shadow DOM popover should close that popover
+[PASS] Moving focus back to the invoker element should not dismiss the popover
+[PASS] Ensure circular/convoluted ancestral relationships are functional
+[PASS] Ensure circular/convoluted ancestral relationships are functional, with a direct showPopover()
+[PASS] Light dismiss of mixed popover types including hints
+[PASS] Hide the target popover during "hide all popovers until"
+[PASS] Show a sibling popover during "hide all popovers until"
+[PASS] Show an unrelated popover during "hide popover"
+[PASS] Show other auto popover during "hide all popover until"
+[PASS] Nested showPopover
+[FAIL] Pointer down in one document and pointer up in another document shouldn't dismiss popover
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-light-dismiss-flat-tree-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-light-dismiss-flat-tree-expected.txt
new file mode 100644
index 0000000..16bb24e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-light-dismiss-flat-tree-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 612, in do_testharness\n    done, rv = handler(result)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py", line 738, in __call__\n    return callback(url, payload)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py", line 755, in process_action\n    result = action_handler(payload)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/actions.py", line 139, in __call__\n    action["origin"] = self.get_element(action["origin"]["selector"])\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/actions.py", line 143, in get_element\n    return self.protocol.select.element_by_selector(element_selector)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py", line 275, in element_by_selector\n    raise ValueError(f"Selector '{element_selector}' matches no elements")\nValueError: Selector '#\69 \6e \6e \65 \72 \50 \6f \70 \6f \76 \65 \72 \54 \6f \67 \67 \6c \65 ' matches no elements\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-light-dismiss-flat-tree-nested-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-light-dismiss-flat-tree-nested-expected.txt
new file mode 100644
index 0000000..16bb24e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/popovers/popover-light-dismiss-flat-tree-nested-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 612, in do_testharness\n    done, rv = handler(result)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py", line 738, in __call__\n    return callback(url, payload)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py", line 755, in process_action\n    result = action_handler(payload)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/actions.py", line 139, in __call__\n    action["origin"] = self.get_element(action["origin"]["selector"])\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/actions.py", line 143, in get_element\n    return self.protocol.select.element_by_selector(element_selector)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py", line 275, in element_by_selector\n    raise ValueError(f"Selector '{element_selector}' matches no elements")\nValueError: Selector '#\69 \6e \6e \65 \72 \50 \6f \70 \6f \76 \65 \72 \54 \6f \67 \67 \6c \65 ' matches no elements\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/css-module/content-type-checking-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/css-module/content-type-checking-expected.txt
new file mode 100644
index 0000000..c0ecfbc8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/css-module/content-type-checking-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected token 'with'
+[NOTRUN] text/css
+[NOTRUN] application/css
+[NOTRUN] text/html+css
+[NOTRUN] text/css;boundary=something
+[NOTRUN] text/css;foo=bar
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/css-module/load-error-events-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/css-module/load-error-events-expected.txt
new file mode 100644
index 0000000..aa041c5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/css-module/load-error-events-expected.txt
@@ -0,0 +1,15 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected token 'with'
+[NOTRUN] inline, 200, parser-inserted
+[NOTRUN] inline, 404, parser-inserted
+[FAIL] src, 200, parser-inserted
+  assert_true: Load event should be fired after script execution expected true got false
+[FAIL] src, 404, parser-inserted
+  assert_unreached: Load event should not be fired. Reached unreachable code
+[FAIL] src, 200, not parser-inserted
+  assert_true: Load event should be fired after script execution expected true got false
+[FAIL] src, 404, not parser-inserted
+  assert_unreached: Load event should not be fired. Reached unreachable code
+[NOTRUN] inline, 200, not parser-inserted
+[NOTRUN] inline, 404, not parser-inserted
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/json-module/load-error-events-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/json-module/load-error-events-expected.txt
new file mode 100644
index 0000000..aa041c5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/json-module/load-error-events-expected.txt
@@ -0,0 +1,15 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected token 'with'
+[NOTRUN] inline, 200, parser-inserted
+[NOTRUN] inline, 404, parser-inserted
+[FAIL] src, 200, parser-inserted
+  assert_true: Load event should be fired after script execution expected true got false
+[FAIL] src, 404, parser-inserted
+  assert_unreached: Load event should not be fired. Reached unreachable code
+[FAIL] src, 200, not parser-inserted
+  assert_true: Load event should be fired after script execution expected true got false
+[FAIL] src, 404, not parser-inserted
+  assert_unreached: Load event should not be fired. Reached unreachable code
+[NOTRUN] inline, 200, not parser-inserted
+[NOTRUN] inline, 404, not parser-inserted
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/json-module/module-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/json-module/module-expected.txt
new file mode 100644
index 0000000..81f5fcd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/json-module/module-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected token 'with'
+[NOTRUN] JSON modules
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/json-module/valid-content-type-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/json-module/valid-content-type-expected.txt
new file mode 100644
index 0000000..158b2ab
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/semantics/scripting-1/the-script-element/json-module/valid-content-type-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected token 'with'
+[NOTRUN] text/json
+[NOTRUN] application/json
+[NOTRUN] text/html+json
+[NOTRUN] image/svg+json
+[NOTRUN] text/json;boundary=something
+[NOTRUN] text/json;foo=bar
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/syntax/charset/without-inheritance-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/syntax/charset/without-inheritance-expected.txt
new file mode 100644
index 0000000..66ab557
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/syntax/charset/without-inheritance-expected.txt
@@ -0,0 +1,25 @@
+This is a testharness.js-based test.
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/after-1kb.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/after-bogus-after-1kb.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/after-bogus.html
+[FAIL] Check http://web-platform.test:8001/html/syntax/charset/after-head-after-1kb-crlf.html
+  assert_not_equals: Check characterSet got disallowed value "windows-1251"
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/after-head-after-1kb.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/after-head-in-1kb-crlf.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/after-head-in-1kb.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/baseline.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/document-write.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/in-comment.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/in-noscript-after-template-after-1kb.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/in-object.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/in-script.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/in-style.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/in-svg.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/in-svg-in-cdata.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/in-template-after-1kb.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/in-template.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/in-title.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/ncr.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/non-ascii-in-comment-before.html
+[PASS] Check http://web-platform.test:8001/html/syntax/charset/non-ascii-in-title-before.html
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/webappapis/scripting/processing-model-2/runtime-error-in-setInterval-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/webappapis/scripting/processing-model-2/runtime-error-in-setInterval-expected.txt
new file mode 100644
index 0000000..7ad0236
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/webappapis/scripting/processing-model-2/runtime-error-in-setInterval-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] window.onerror - runtime error in setInterval
+  assert_equals: second arg expected "http://web-platform.test:8001/html/webappapis/scripting/processing-model-2/runtime-error-in-setInterval.html" but got ""
+[PASS] window.onerror - runtime error in setInterval (column)
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/webappapis/scripting/processing-model-2/runtime-error-in-setTimeout-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/webappapis/scripting/processing-model-2/runtime-error-in-setTimeout-expected.txt
new file mode 100644
index 0000000..9e6cdc53
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/html/webappapis/scripting/processing-model-2/runtime-error-in-setTimeout-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] window.onerror - runtime error in setTimeout
+  assert_equals: second arg expected "http://web-platform.test:8001/html/webappapis/scripting/processing-model-2/runtime-error-in-setTimeout.html" but got ""
+[PASS] window.onerror - runtime error in setTimeout (column)
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub-expected.txt
new file mode 100644
index 0000000..b3eec62cd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Error: Tried to run in a non-testharness window without a call to set_test_context
+[NOTRUN] Attribute allow="idle-detection" in top-level frame allows same-origin relocation.
+[NOTRUN] Attribute allow="idle-detection" in top-level frame allows workers in same-origin relocation.
+[NOTRUN] Attribute allow="idle-detection" in top-level frame disallows cross-origin relocation.
+[NOTRUN] Attribute allow="idle-detection" in top-level frame disallows workers in cross-origin relocation.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy-attribute.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy-attribute.https.sub-expected.txt
new file mode 100644
index 0000000..2c12ad60
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy-attribute.https.sub-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Error: Tried to run in a non-testharness window without a call to set_test_context
+[NOTRUN] Attribute allow="idle-detection" in top-level frame can be enabled in same-origin iframe using Permissions Policy "idle-detection".
+[NOTRUN] Attribute allow="idle-detection" in top-level frame can be enabled in a worker in same-origin iframe using Permissions Policy "idle-detection".
+[NOTRUN] Attribute allow="idle-detection" in top-level frame can be enabled in cross-origin iframe using Permissions Policy "idle-detection".
+[NOTRUN] Attribute allow="idle-detection" in top-level frame can be enabled in a worker in cross-origin iframe using Permissions Policy "idle-detection".
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub-expected.txt
new file mode 100644
index 0000000..c121ec7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Error: Tried to run in a non-testharness window without a call to set_test_context
+[NOTRUN] Permissions-Policy idle-detection=* explicity set by top-level frame allows the top-level document.
+[NOTRUN] Permissions-Policy idle-detection=* explicity set by top-level frame allows same-origin iframes.
+[NOTRUN] Permissions-Policy idle-detection=* explicity set by top-level frame allows workers in same-origin iframes.
+[NOTRUN] Permissions-Policy idle-detection=* explicity set by top-level frame allows cross-origin iframes.
+[NOTRUN] Permissions-Policy idle-detection=* explicity set by top-level frame allows workers in cross-origin iframes.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-default-permissions-policy.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-default-permissions-policy.https.sub-expected.txt
new file mode 100644
index 0000000..9f3322b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-default-permissions-policy.https.sub-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Error: Tried to run in a non-testharness window without a call to set_test_context
+[NOTRUN] Default "idle-detection" permissions policy "self" allows the top-level document.
+[NOTRUN] Default "idle-detection" permissions policy "self" allows same-origin iframes.
+[NOTRUN] Default "idle-detection" permissions policy "self" disallows cross-origin iframes.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-detached-frame.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-detached-frame.https-expected.txt
new file mode 100644
index 0000000..8de77113
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/idle-detection-detached-frame.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Using an IdleDetector from a detached frame
+  promise_test: Unhandled rejection with value: object "Error: Tried to run in a non-testharness window without a call to set_test_context"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/page-visibility.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/page-visibility.https-expected.txt
new file mode 100644
index 0000000..fc514f3e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/idle-detection/page-visibility.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Page visibility.
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/infrastructure/server/test-pac-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/infrastructure/server/test-pac-expected.txt
new file mode 100644
index 0000000..2e6d2cb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/infrastructure/server/test-pac-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] test that PAC metadata is respected
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-exec-command-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-exec-command-expected.txt
new file mode 100644
index 0000000..6c219550
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-exec-command-expected.txt
@@ -0,0 +1,383 @@
+This is a testharness.js-based test.
+Found 307 tests; 234 PASS, 73 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] Calling execCommand("insertText", false, a) (calling execCommand)
+[PASS] Calling execCommand("insertText", false, a) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("insertText", false, a) (inputType value)
+[PASS] Calling execCommand("insertText", false, a) (data value)
+[PASS] Calling execCommand("insertText", false, a) (dataTransfer value)
+[PASS] Calling execCommand("insertText", false, bc) (calling execCommand)
+[PASS] Calling execCommand("insertText", false, bc) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("insertText", false, bc) (inputType value)
+[PASS] Calling execCommand("insertText", false, bc) (data value)
+[PASS] Calling execCommand("insertText", false, bc) (dataTransfer value)
+[PASS] execCommand("insertText") should insert "abc" into the editor
+[PASS] Calling execCommand("insertOrderedList", false, null) (calling execCommand)
+[PASS] Calling execCommand("insertOrderedList", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("insertOrderedList", false, null) (inputType value)
+[PASS] Calling execCommand("insertOrderedList", false, null) (data value)
+[PASS] Calling execCommand("insertOrderedList", false, null) (dataTransfer value)
+[PASS] execCommand("insertOrderedList") should make <ol> and wrap the text with it
+[PASS] Calling execCommand("insertUnorderedList", false, null) (calling execCommand)
+[PASS] Calling execCommand("insertUnorderedList", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("insertUnorderedList", false, null) (inputType value)
+[PASS] Calling execCommand("insertUnorderedList", false, null) (data value)
+[PASS] Calling execCommand("insertUnorderedList", false, null) (dataTransfer value)
+[PASS] execCommand("insertUnorderedList") should make <ul> and wrap the text with it
+[PASS] Calling execCommand("insertLineBreak", false, null) (calling execCommand)
+[PASS] Calling execCommand("insertLineBreak", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("insertLineBreak", false, null) (inputType value)
+[PASS] Calling execCommand("insertLineBreak", false, null) (data value)
+[PASS] Calling execCommand("insertLineBreak", false, null) (dataTransfer value)
+[PASS] Calling execCommand("insertParagraph", false, null) (calling execCommand)
+[PASS] Calling execCommand("insertParagraph", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("insertParagraph", false, null) (inputType value)
+[PASS] Calling execCommand("insertParagraph", false, null) (data value)
+[PASS] Calling execCommand("insertParagraph", false, null) (dataTransfer value)
+[PASS] Calling execCommand("insertHorizontalRule", false, null) (calling execCommand)
+[PASS] Calling execCommand("insertHorizontalRule", false, null) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("insertHorizontalRule", false, null) (inputType value)
+  assert_equals: expected "insertHorizontalRule" but got ""
+[PASS] Calling execCommand("insertHorizontalRule", false, null) (data value)
+[PASS] Calling execCommand("insertHorizontalRule", false, null) (dataTransfer value)
+[PASS] Calling execCommand("bold", false, null) (calling execCommand)
+[PASS] Calling execCommand("bold", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("bold", false, null) (inputType value)
+[PASS] Calling execCommand("bold", false, null) (data value)
+[PASS] Calling execCommand("bold", false, null) (dataTransfer value)
+[PASS] execCommand("bold") should wrap selected text with <b> element
+[PASS] Calling execCommand("italic", false, null) (calling execCommand)
+[PASS] Calling execCommand("italic", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("italic", false, null) (inputType value)
+[PASS] Calling execCommand("italic", false, null) (data value)
+[PASS] Calling execCommand("italic", false, null) (dataTransfer value)
+[PASS] execCommand("italic") should wrap selected text with <i> element
+[PASS] Calling execCommand("underline", false, null) (calling execCommand)
+[PASS] Calling execCommand("underline", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("underline", false, null) (inputType value)
+[PASS] Calling execCommand("underline", false, null) (data value)
+[PASS] Calling execCommand("underline", false, null) (dataTransfer value)
+[PASS] execCommand("underline") should wrap selected text with <u> element
+[PASS] Calling execCommand("strikeThrough", false, null) (calling execCommand)
+[PASS] Calling execCommand("strikeThrough", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("strikeThrough", false, null) (inputType value)
+[PASS] Calling execCommand("strikeThrough", false, null) (data value)
+[PASS] Calling execCommand("strikeThrough", false, null) (dataTransfer value)
+[PASS] execCommand("strikeThrough") should wrap selected text with <strike> element
+[PASS] Calling execCommand("superscript", false, null) (calling execCommand)
+[PASS] Calling execCommand("superscript", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("superscript", false, null) (inputType value)
+[PASS] Calling execCommand("superscript", false, null) (data value)
+[PASS] Calling execCommand("superscript", false, null) (dataTransfer value)
+[PASS] execCommand("superscript") should wrap selected text with <sup> element
+[PASS] Calling execCommand("subscript", false, null) (calling execCommand)
+[PASS] Calling execCommand("subscript", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("subscript", false, null) (inputType value)
+[PASS] Calling execCommand("subscript", false, null) (data value)
+[PASS] Calling execCommand("subscript", false, null) (dataTransfer value)
+[PASS] execCommand("subscript") should wrap selected text with <sub> element
+[PASS] Calling execCommand("backColor", false, #FF0000) (calling execCommand)
+[PASS] Calling execCommand("backColor", false, #FF0000) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("backColor", false, #FF0000) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("backColor", false, #FF0000) (data value)
+  assert_equals: expected (string) "rgb(255, 0, 0)" but got (object) null
+[PASS] Calling execCommand("backColor", false, #FF0000) (dataTransfer value)
+[PASS] Calling execCommand("backColor", false, #00FF00FF) (calling execCommand)
+[PASS] Calling execCommand("backColor", false, #00FF00FF) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("backColor", false, #00FF00FF) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("backColor", false, #00FF00FF) (data value)
+  assert_equals: expected (string) "rgb(0, 255, 0)" but got (object) null
+[PASS] Calling execCommand("backColor", false, #00FF00FF) (dataTransfer value)
+[PASS] Calling execCommand("backColor", false, #0000FF88) (calling execCommand)
+[PASS] Calling execCommand("backColor", false, #0000FF88) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("backColor", false, #0000FF88) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("backColor", false, #0000FF88) (data value)
+  assert_equals: expected (string) "rgba(0, 0, 255, 0.533)" but got (object) null
+[PASS] Calling execCommand("backColor", false, #0000FF88) (dataTransfer value)
+[PASS] Calling execCommand("backColor", false, orange) (calling execCommand)
+[PASS] Calling execCommand("backColor", false, orange) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("backColor", false, orange) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("backColor", false, orange) (data value)
+  assert_equals: expected (string) "rgb(255, 165, 0)" but got (object) null
+[PASS] Calling execCommand("backColor", false, orange) (dataTransfer value)
+[PASS] Calling execCommand("backColor", false, Inherit) (calling execCommand)
+[PASS] Calling execCommand("backColor", false, Inherit) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("backColor", false, Inherit) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("backColor", false, Inherit) (data value)
+  assert_equals: expected (string) "inherit" but got (object) null
+[PASS] Calling execCommand("backColor", false, Inherit) (dataTransfer value)
+[PASS] Calling execCommand("backColor", false, Initial) (calling execCommand)
+[PASS] Calling execCommand("backColor", false, Initial) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("backColor", false, Initial) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("backColor", false, Initial) (data value)
+  assert_equals: expected (string) "initial" but got (object) null
+[PASS] Calling execCommand("backColor", false, Initial) (dataTransfer value)
+[PASS] Calling execCommand("backColor", false, Reset) (calling execCommand)
+[PASS] Calling execCommand("backColor", false, Reset) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("backColor", false, Reset) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("backColor", false, Reset) (data value)
+  assert_equals: expected (string) "reset" but got (object) null
+[PASS] Calling execCommand("backColor", false, Reset) (dataTransfer value)
+[PASS] Calling execCommand("backColor", false, transparent) (calling execCommand)
+[PASS] Calling execCommand("backColor", false, transparent) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("backColor", false, transparent) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("backColor", false, transparent) (data value)
+  assert_equals: expected (string) "rgba(0, 0, 0, 0)" but got (object) null
+[PASS] Calling execCommand("backColor", false, transparent) (dataTransfer value)
+[PASS] Calling execCommand("backColor", false, CurrentColor) (calling execCommand)
+[PASS] Calling execCommand("backColor", false, CurrentColor) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("backColor", false, CurrentColor) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("backColor", false, CurrentColor) (data value)
+  assert_equals: expected (string) "currentcolor" but got (object) null
+[PASS] Calling execCommand("backColor", false, CurrentColor) (dataTransfer value)
+[PASS] Calling execCommand("backColor", false, Invalid-Value) (calling execCommand)
+[PASS] Calling execCommand("backColor", false, Invalid-Value) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("backColor", false, Invalid-Value) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("backColor", false, Invalid-Value) (data value)
+  assert_equals: expected (string) "Invalid-Value" but got (object) null
+[PASS] Calling execCommand("backColor", false, Invalid-Value) (dataTransfer value)
+[PASS] Calling execCommand("foreColor", false, #FF0000) (calling execCommand)
+[PASS] Calling execCommand("foreColor", false, #FF0000) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("foreColor", false, #FF0000) (inputType value)
+  assert_equals: expected "formatFontColor" but got ""
+[FAIL] Calling execCommand("foreColor", false, #FF0000) (data value)
+  assert_equals: expected (string) "rgb(255, 0, 0)" but got (object) null
+[PASS] Calling execCommand("foreColor", false, #FF0000) (dataTransfer value)
+[PASS] Calling execCommand("foreColor", false, #00FF00FF) (calling execCommand)
+[PASS] Calling execCommand("foreColor", false, #00FF00FF) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("foreColor", false, #00FF00FF) (inputType value)
+  assert_equals: expected "formatFontColor" but got ""
+[FAIL] Calling execCommand("foreColor", false, #00FF00FF) (data value)
+  assert_equals: expected (string) "rgb(0, 255, 0)" but got (object) null
+[PASS] Calling execCommand("foreColor", false, #00FF00FF) (dataTransfer value)
+[PASS] Calling execCommand("foreColor", false, #0000FF88) (calling execCommand)
+[PASS] Calling execCommand("foreColor", false, #0000FF88) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("foreColor", false, #0000FF88) (inputType value)
+  assert_equals: expected "formatFontColor" but got ""
+[FAIL] Calling execCommand("foreColor", false, #0000FF88) (data value)
+  assert_equals: expected (string) "rgba(0, 0, 255, 0.533)" but got (object) null
+[PASS] Calling execCommand("foreColor", false, #0000FF88) (dataTransfer value)
+[PASS] Calling execCommand("foreColor", false, orange) (calling execCommand)
+[PASS] Calling execCommand("foreColor", false, orange) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("foreColor", false, orange) (inputType value)
+  assert_equals: expected "formatFontColor" but got ""
+[FAIL] Calling execCommand("foreColor", false, orange) (data value)
+  assert_equals: expected (string) "rgb(255, 165, 0)" but got (object) null
+[PASS] Calling execCommand("foreColor", false, orange) (dataTransfer value)
+[PASS] Calling execCommand("foreColor", false, Inherit) (calling execCommand)
+[PASS] Calling execCommand("foreColor", false, Inherit) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("foreColor", false, Inherit) (inputType value)
+  assert_equals: expected "formatFontColor" but got ""
+[FAIL] Calling execCommand("foreColor", false, Inherit) (data value)
+  assert_equals: expected (string) "inherit" but got (object) null
+[PASS] Calling execCommand("foreColor", false, Inherit) (dataTransfer value)
+[PASS] Calling execCommand("foreColor", false, Initial) (calling execCommand)
+[PASS] Calling execCommand("foreColor", false, Initial) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("foreColor", false, Initial) (inputType value)
+  assert_equals: expected "formatFontColor" but got ""
+[FAIL] Calling execCommand("foreColor", false, Initial) (data value)
+  assert_equals: expected (string) "initial" but got (object) null
+[PASS] Calling execCommand("foreColor", false, Initial) (dataTransfer value)
+[PASS] Calling execCommand("foreColor", false, Reset) (calling execCommand)
+[PASS] Calling execCommand("foreColor", false, Reset) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("foreColor", false, Reset) (inputType value)
+  assert_equals: expected "formatFontColor" but got ""
+[FAIL] Calling execCommand("foreColor", false, Reset) (data value)
+  assert_equals: expected (string) "reset" but got (object) null
+[PASS] Calling execCommand("foreColor", false, Reset) (dataTransfer value)
+[PASS] Calling execCommand("foreColor", false, transparent) (calling execCommand)
+[PASS] Calling execCommand("foreColor", false, transparent) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("foreColor", false, transparent) (inputType value)
+  assert_equals: expected "formatFontColor" but got ""
+[FAIL] Calling execCommand("foreColor", false, transparent) (data value)
+  assert_equals: expected (string) "rgba(0, 0, 0, 0)" but got (object) null
+[PASS] Calling execCommand("foreColor", false, transparent) (dataTransfer value)
+[PASS] Calling execCommand("foreColor", false, CurrentColor) (calling execCommand)
+[PASS] Calling execCommand("foreColor", false, CurrentColor) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("foreColor", false, CurrentColor) (inputType value)
+  assert_equals: expected "formatFontColor" but got ""
+[FAIL] Calling execCommand("foreColor", false, CurrentColor) (data value)
+  assert_equals: expected (string) "currentcolor" but got (object) null
+[PASS] Calling execCommand("foreColor", false, CurrentColor) (dataTransfer value)
+[PASS] Calling execCommand("foreColor", false, Invalid-Value) (calling execCommand)
+[PASS] Calling execCommand("foreColor", false, Invalid-Value) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("foreColor", false, Invalid-Value) (inputType value)
+  assert_equals: expected "formatFontColor" but got ""
+[FAIL] Calling execCommand("foreColor", false, Invalid-Value) (data value)
+  assert_equals: expected (string) "Invalid-Value" but got (object) null
+[PASS] Calling execCommand("foreColor", false, Invalid-Value) (dataTransfer value)
+[PASS] Calling execCommand("hiliteColor", false, #FF0000) (calling execCommand)
+[PASS] Calling execCommand("hiliteColor", false, #FF0000) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("hiliteColor", false, #FF0000) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("hiliteColor", false, #FF0000) (data value)
+  assert_equals: expected (string) "rgb(255, 0, 0)" but got (object) null
+[PASS] Calling execCommand("hiliteColor", false, #FF0000) (dataTransfer value)
+[PASS] Calling execCommand("hiliteColor", false, #00FF00FF) (calling execCommand)
+[PASS] Calling execCommand("hiliteColor", false, #00FF00FF) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("hiliteColor", false, #00FF00FF) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("hiliteColor", false, #00FF00FF) (data value)
+  assert_equals: expected (string) "rgb(0, 255, 0)" but got (object) null
+[PASS] Calling execCommand("hiliteColor", false, #00FF00FF) (dataTransfer value)
+[PASS] Calling execCommand("hiliteColor", false, #0000FF88) (calling execCommand)
+[PASS] Calling execCommand("hiliteColor", false, #0000FF88) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("hiliteColor", false, #0000FF88) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("hiliteColor", false, #0000FF88) (data value)
+  assert_equals: expected (string) "rgba(0, 0, 255, 0.533)" but got (object) null
+[PASS] Calling execCommand("hiliteColor", false, #0000FF88) (dataTransfer value)
+[PASS] Calling execCommand("hiliteColor", false, orange) (calling execCommand)
+[PASS] Calling execCommand("hiliteColor", false, orange) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("hiliteColor", false, orange) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("hiliteColor", false, orange) (data value)
+  assert_equals: expected (string) "rgb(255, 165, 0)" but got (object) null
+[PASS] Calling execCommand("hiliteColor", false, orange) (dataTransfer value)
+[PASS] Calling execCommand("hiliteColor", false, Inherit) (calling execCommand)
+[PASS] Calling execCommand("hiliteColor", false, Inherit) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("hiliteColor", false, Inherit) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("hiliteColor", false, Inherit) (data value)
+  assert_equals: expected (string) "inherit" but got (object) null
+[PASS] Calling execCommand("hiliteColor", false, Inherit) (dataTransfer value)
+[PASS] Calling execCommand("hiliteColor", false, Initial) (calling execCommand)
+[PASS] Calling execCommand("hiliteColor", false, Initial) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("hiliteColor", false, Initial) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("hiliteColor", false, Initial) (data value)
+  assert_equals: expected (string) "initial" but got (object) null
+[PASS] Calling execCommand("hiliteColor", false, Initial) (dataTransfer value)
+[PASS] Calling execCommand("hiliteColor", false, Reset) (calling execCommand)
+[PASS] Calling execCommand("hiliteColor", false, Reset) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("hiliteColor", false, Reset) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("hiliteColor", false, Reset) (data value)
+  assert_equals: expected (string) "reset" but got (object) null
+[PASS] Calling execCommand("hiliteColor", false, Reset) (dataTransfer value)
+[PASS] Calling execCommand("hiliteColor", false, transparent) (calling execCommand)
+[PASS] Calling execCommand("hiliteColor", false, transparent) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("hiliteColor", false, transparent) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("hiliteColor", false, transparent) (data value)
+  assert_equals: expected (string) "rgba(0, 0, 0, 0)" but got (object) null
+[PASS] Calling execCommand("hiliteColor", false, transparent) (dataTransfer value)
+[PASS] Calling execCommand("hiliteColor", false, CurrentColor) (calling execCommand)
+[PASS] Calling execCommand("hiliteColor", false, CurrentColor) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("hiliteColor", false, CurrentColor) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("hiliteColor", false, CurrentColor) (data value)
+  assert_equals: expected (string) "currentcolor" but got (object) null
+[PASS] Calling execCommand("hiliteColor", false, CurrentColor) (dataTransfer value)
+[PASS] Calling execCommand("hiliteColor", false, Invalid-Value) (calling execCommand)
+[PASS] Calling execCommand("hiliteColor", false, Invalid-Value) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("hiliteColor", false, Invalid-Value) (inputType value)
+  assert_equals: expected "formatBackColor" but got ""
+[FAIL] Calling execCommand("hiliteColor", false, Invalid-Value) (data value)
+  assert_equals: expected (string) "Invalid-Value" but got (object) null
+[PASS] Calling execCommand("hiliteColor", false, Invalid-Value) (dataTransfer value)
+[PASS] Calling execCommand("fontName", false, monospace) (calling execCommand)
+[PASS] Calling execCommand("fontName", false, monospace) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("fontName", false, monospace) (inputType value)
+  assert_equals: expected "formatFontName" but got ""
+[FAIL] Calling execCommand("fontName", false, monospace) (data value)
+  assert_equals: expected (string) "monospace" but got (object) null
+[PASS] Calling execCommand("fontName", false, monospace) (dataTransfer value)
+[PASS] Calling execCommand("fontName", false,  monospace ) (calling execCommand)
+[PASS] Calling execCommand("fontName", false,  monospace ) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("fontName", false,  monospace ) (inputType value)
+  assert_equals: expected "formatFontName" but got ""
+[FAIL] Calling execCommand("fontName", false,  monospace ) (data value)
+  assert_equals: expected (string) " monospace " but got (object) null
+[PASS] Calling execCommand("fontName", false,  monospace ) (dataTransfer value)
+[PASS] Calling execCommand("fontName", false,   monospace  ) (calling execCommand)
+[PASS] Calling execCommand("fontName", false,   monospace  ) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("fontName", false,   monospace  ) (inputType value)
+  assert_equals: expected "formatFontName" but got ""
+[FAIL] Calling execCommand("fontName", false,   monospace  ) (data value)
+  assert_equals: expected (string) "  monospace  " but got (object) null
+[PASS] Calling execCommand("fontName", false,   monospace  ) (dataTransfer value)
+[PASS] Calling execCommand("justifyCenter", false, null) (calling execCommand)
+[PASS] Calling execCommand("justifyCenter", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("justifyCenter", false, null) (inputType value)
+[PASS] Calling execCommand("justifyCenter", false, null) (data value)
+[PASS] Calling execCommand("justifyCenter", false, null) (dataTransfer value)
+[PASS] execCommand("justifyCenter") should wrap the text with <div> element whose text-align is center
+[PASS] Calling execCommand("justifyFull", false, null) (calling execCommand)
+[PASS] Calling execCommand("justifyFull", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("justifyFull", false, null) (inputType value)
+[PASS] Calling execCommand("justifyFull", false, null) (data value)
+[PASS] Calling execCommand("justifyFull", false, null) (dataTransfer value)
+[PASS] execCommand("justifyFull") should wrap the text with <div> element whose text-align is justify
+[PASS] Calling execCommand("justifyRight", false, null) (calling execCommand)
+[PASS] Calling execCommand("justifyRight", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("justifyRight", false, null) (inputType value)
+[PASS] Calling execCommand("justifyRight", false, null) (data value)
+[PASS] Calling execCommand("justifyRight", false, null) (dataTransfer value)
+[PASS] execCommand("justifyRight") should wrap the text with <div> element whose text-align is right
+[PASS] Calling execCommand("justifyLeft", false, null) (calling execCommand)
+[PASS] Calling execCommand("justifyLeft", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("justifyLeft", false, null) (inputType value)
+[PASS] Calling execCommand("justifyLeft", false, null) (data value)
+[PASS] Calling execCommand("justifyLeft", false, null) (dataTransfer value)
+[PASS] execCommand("justifyLeft") should wrap the text with <div> element whose text-align is left
+[PASS] Calling execCommand("removeFormat", false, null) (calling execCommand)
+[PASS] Calling execCommand("removeFormat", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("removeFormat", false, null) (inputType value)
+[PASS] Calling execCommand("removeFormat", false, null) (data value)
+[PASS] Calling execCommand("removeFormat", false, null) (dataTransfer value)
+[PASS] execCommand("removeFormat") should remove the style of current block
+[PASS] Calling execCommand("indent", false, null) (calling execCommand)
+[PASS] Calling execCommand("indent", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("indent", false, null) (inputType value)
+[PASS] Calling execCommand("indent", false, null) (data value)
+[PASS] Calling execCommand("indent", false, null) (dataTransfer value)
+[PASS] Calling execCommand("outdent", false, null) (calling execCommand)
+[PASS] Calling execCommand("outdent", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("outdent", false, null) (inputType value)
+[PASS] Calling execCommand("outdent", false, null) (data value)
+[PASS] Calling execCommand("outdent", false, null) (dataTransfer value)
+[PASS] Set of execCommand("indent") and execCommand("outdent") should keep same DOM tree
+[PASS] Calling execCommand("copy", false, null) (calling execCommand)
+[PASS] Calling execCommand("copy", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("copy", false, null) (inputType value)
+[PASS] Calling execCommand("cut", false, null) (calling execCommand)
+[PASS] Calling execCommand("cut", false, null) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("cut", false, null) (inputType value)
+  assert_equals: expected "deleteByCut" but got "NO_INPUT_EVENT_FIRED"
+[PASS] Calling execCommand("paste", false, null) (calling execCommand)
+[PASS] Calling execCommand("paste", false, null) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("paste", false, null) (inputType value)
+  assert_equals: expected "insertFromPaste" but got "NO_INPUT_EVENT_FIRED"
+[PASS] Calling execCommand("createLink", false, https://example.com/) (calling execCommand)
+[PASS] Calling execCommand("createLink", false, https://example.com/) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("createLink", false, https://example.com/) (inputType value)
+  assert_equals: expected "insertLink" but got ""
+[FAIL] Calling execCommand("createLink", false, https://example.com/) (data value)
+  assert_equals: expected (string) "https://example.com/" but got (object) null
+[PASS] Calling execCommand("createLink", false, https://example.com/) (dataTransfer value)
+[PASS] execCommand("createLink") should create a link with absolute URL
+[PASS] Calling execCommand("unlink", false, null) (calling execCommand)
+[PASS] Calling execCommand("unlink", false, null) (shouldn't fire beforeinput)
+[PASS] Calling execCommand("unlink", false, null) (inputType value)
+[PASS] Calling execCommand("unlink", false, null) (data value)
+[PASS] Calling execCommand("unlink", false, null) (dataTransfer value)
+[PASS] execCommand("createLink") should remove the link
+[PASS] Calling execCommand("createLink", false, foo.html) (calling execCommand)
+[PASS] Calling execCommand("createLink", false, foo.html) (shouldn't fire beforeinput)
+[FAIL] Calling execCommand("createLink", false, foo.html) (inputType value)
+  assert_equals: expected "insertLink" but got ""
+[FAIL] Calling execCommand("createLink", false, foo.html) (data value)
+  assert_equals: expected (string) "foo.html" but got (object) null
+[PASS] Calling execCommand("createLink", false, foo.html) (dataTransfer value)
+[PASS] execCommand("createLink") should create a link with relative URL
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-get-target-ranges-non-collapsed-selection.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-get-target-ranges-non-collapsed-selection.tentative-expected.txt
new file mode 100644
index 0000000..cc1168a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-get-target-ranges-non-collapsed-selection.tentative-expected.txt
@@ -0,0 +1,103 @@
+This is a testharness.js-based test.
+Found 70 tests; 40 PASS, 30 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] TypingA at "<p>{abc}</p>"
+[PASS] TypingA at "<p>{abc}<br></p>"
+[PASS] TypingA at "<p>{<img>}</p>"
+[PASS] TypingA at "<p>{<img>}<br></p>"
+[FAIL] TypingA at "<p>{ abc }</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \" a \", 0) - (#text \" a \", 5)" but got "(#text \" a \", 1) - (#text \" a \", 4)"
+[FAIL] TypingA at "<p>abc   [</p><p>]   def</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 3)" but got "(#text \"abcadef\", 6) - (<p>, 0)"
+[PASS] TypingA at "<p>ab[c</p><p>d]ef</p>"
+[PASS] TypingA at "<p>ab[c </p><p> d]ef</p>"
+[FAIL] TypingA at "<p>ab[c </p><p>] def</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abadef\", 2) - (#text \"\", 1)" but got "(#text \"abadef\", 2) - (<p>, 0)"
+[FAIL] TypingA at "<p>abc [</p><p>] def</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 1)" but got "(#text \"abcadef\", 4) - (<p>, 0)"
+[FAIL] TypingA at "<p>abc [</p><p> ]def</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 1)" but got "(#text \"abcadef\", 4) - (<p>, 0)"
+[FAIL] TypingA at "<p>abc[<img>]def</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abca\", 3) - (#text \"def\", 0)" but got "(<p>, 1) - (<p>, 2)"
+[PASS] TypingA at "<div>abc[<hr>]def</div>"
+[FAIL] TypingA at "<div>abc [<hr>]def</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abca\", 3) - (#text \"def\", 0)" but got "(#text \"abca\", 4) - (#text \"def\", 0)"
+[FAIL] TypingA at "<div>abc [<hr>] def</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abca\", 3) - (#text \"def\", 1)" but got "(#text \"abca\", 4) - (#text \"def\", 0)"
+[FAIL] TypingA at "<div>abc {<hr>} def</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abca\", 3) - (#text \"def\", 1)" but got "(#text \"abca\", 4) - (#text \"def\", 0)"
+[PASS] TypingA at "<p>abc{<br>}def</p>"
+[FAIL] TypingA at "<div>abc[<p>]def<br>ghi</p></div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 0)" but got "(#text \"abcadef\", 3) - (<p>, 0)"
+[FAIL] TypingA at "<div>abc   [<p>]   def<br>ghi</p></div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 3)" but got "(#text \"abcadef\", 6) - (<p>, 0)"
+[PASS] TypingA at "<div><p>abc[</p>]def</div>"
+[FAIL] TypingA at "<div><p>abc   [</p>]   def</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 3)" but got "(#text \"abcadef\", 6) - (#text \"\", 0)"
+[FAIL] TypingA at "<div>abc[<ul><li>]def</li></ul>ghi</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 0)" but got "(#text \"abcadef\", 3) - (<li>, 0)"
+[FAIL] TypingA at "<div>abc  [<ul><li>] def </li></ul>  ghi</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 1)" but got "(#text \"abcadef\", 5) - (<li>, 0)"
+[PASS] TypingA at "<div>abc<ul><li>def[</li></ul>]ghi</div>"
+[FAIL] TypingA at "<div>abc <ul><li>  def  [</li></ul>] ghi</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"  defaghi\", 5) - (#text \"\", 1)" but got "(#text \"  defaghi\", 7) - (#text \"\", 0)"
+[FAIL] TypingA at "<div>abc[<ul><li>]def</li><li>ghi</li></ul>jkl</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 0)" but got "(#text \"abcadef\", 3) - (<li>, 0)"
+[FAIL] TypingA at "<div>abc[<ul><li>def</li><li>]ghi</li></ul>jkl</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcaghi\", 3) - (#text \"\", 0)" but got "(#text \"abcaghi\", 3) - (<li>, 0)"
+[FAIL] TypingA at "<div>abc<ul><li>def[</li><li>]ghi</li></ul>jkl</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"defaghi\", 3) - (#text \"\", 0)" but got "(#text \"defaghi\", 3) - (<li>, 0)"
+[PASS] TypingA at "<div>abc<ul><li>def</li><li>ghi[</li></ul>]jkl</div>"
+[PASS] TypingA at "<div>abc<ul><li>def[</li><li>ghi</li></ul>]jkl</div>"
+[PASS] TypingA at "<p>abc[</p><p>}<br></p>"
+[PASS] TypingA at "<p>abc[<span contenteditable="false">def</span>]ghi</p>"
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>d]ef</td></tr></table>"
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>def</td></tr><tr><td>ghi</td><td>j]kl</td></tr></table>"
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>def</td></tr></table><table><tr><td>ghi</td><td>j]kl</td></tr></table>"
+[PASS] TypingA at "<p>{abc}</p>" - comparing innerHTML
+[PASS] TypingA at "<p>{abc}<br></p>" - comparing innerHTML
+[PASS] TypingA at "<p>{<img>}</p>" - comparing innerHTML
+[PASS] TypingA at "<p>{<img>}<br></p>" - comparing innerHTML
+[FAIL] TypingA at "<p>{ abc }</p>" - comparing innerHTML
+  assert_equals: expected "<p>a</p>" but got "<p> a </p>"
+[PASS] TypingA at "<p>abc   [</p><p>]   def</p>" - comparing innerHTML
+[PASS] TypingA at "<p>ab[c</p><p>d]ef</p>" - comparing innerHTML
+[PASS] TypingA at "<p>ab[c </p><p> d]ef</p>" - comparing innerHTML
+[PASS] TypingA at "<p>ab[c </p><p>] def</p>" - comparing innerHTML
+[PASS] TypingA at "<p>abc [</p><p>] def</p>" - comparing innerHTML
+[PASS] TypingA at "<p>abc [</p><p> ]def</p>" - comparing innerHTML
+[PASS] TypingA at "<p>abc[<img>]def</p>" - comparing innerHTML
+[PASS] TypingA at "<div>abc[<hr>]def</div>" - comparing innerHTML
+[PASS] TypingA at "<div>abc [<hr>]def</div>" - comparing innerHTML
+[PASS] TypingA at "<div>abc [<hr>] def</div>" - comparing innerHTML
+[PASS] TypingA at "<div>abc {<hr>} def</div>" - comparing innerHTML
+[PASS] TypingA at "<p>abc{<br>}def</p>" - comparing innerHTML
+[PASS] TypingA at "<div>abc[<p>]def<br>ghi</p></div>" - comparing innerHTML
+[PASS] TypingA at "<div>abc   [<p>]   def<br>ghi</p></div>" - comparing innerHTML
+[FAIL] TypingA at "<div><p>abc[</p>]def</div>" - comparing innerHTML
+  assert_in_array: value "<p>abcadef</p>" not in array ["<div><p>abcadef</p></div>", "<div><p>abcadef<br></p></div>"]
+[FAIL] TypingA at "<div><p>abc   [</p>]   def</div>" - comparing innerHTML
+  assert_in_array: value "<p>abcadef</p>" not in array ["<div><p>abcadef</p></div>", "<div><p>abcadef<br></p></div>"]
+[FAIL] TypingA at "<div>abc[<ul><li>]def</li></ul>ghi</div>" - comparing innerHTML
+  assert_equals: expected "<div>abcadefghi</div>" but got "abcadefghi<br>"
+[FAIL] TypingA at "<div>abc  [<ul><li>] def </li></ul>  ghi</div>" - comparing innerHTML
+  assert_equals: expected "<div>abcadefghi</div>" but got "abcadef&nbsp; ghi<br>"
+[FAIL] TypingA at "<div>abc<ul><li>def[</li></ul>]ghi</div>" - comparing innerHTML
+  assert_equals: expected "<div>abc<ul><li>defaghi</li></ul></div>" but got "abc<ul><li>defaghi</li></ul>"
+[FAIL] TypingA at "<div>abc <ul><li>  def  [</li></ul>] ghi</div>" - comparing innerHTML
+  assert_in_array: value "abc <ul><li>  defaghi</li></ul>" not in array ["<div>abc <ul><li>  defaghi</li></ul></div>", "<div>abc <ul><li>defaghi</li></ul></div>", "<div>abc<ul><li>defaghi</li></ul></div>"]
+[FAIL] TypingA at "<div>abc[<ul><li>]def</li><li>ghi</li></ul>jkl</div>" - comparing innerHTML
+  assert_equals: expected "<div>abcadef<ul><li>ghi</li></ul>jkl</div>" but got "abcadef<ul><li>ghi</li></ul>jkl<br>"
+[FAIL] TypingA at "<div>abc[<ul><li>def</li><li>]ghi</li></ul>jkl</div>" - comparing innerHTML
+  assert_in_array: value "abcaghijkl<br>" not in array ["<div>abcaghijkl</div>", "<div>abcaghijkl<br></div>"]
+[FAIL] TypingA at "<div>abc<ul><li>def[</li><li>]ghi</li></ul>jkl</div>" - comparing innerHTML
+  assert_equals: expected "<div>abc<ul><li>defaghi</li></ul>jkl</div>" but got "abc<ul><li>defaghi</li></ul>jkl<br>"
+[FAIL] TypingA at "<div>abc<ul><li>def</li><li>ghi[</li></ul>]jkl</div>" - comparing innerHTML
+  assert_equals: expected "<div>abc<ul><li>def</li><li>ghiajkl</li></ul></div>" but got "abc<ul><li>def</li><li>ghiajkl</li></ul>"
+[FAIL] TypingA at "<div>abc<ul><li>def[</li><li>ghi</li></ul>]jkl</div>" - comparing innerHTML
+  assert_equals: expected "<div>abc<ul><li>defajkl</li></ul></div>" but got "abc<ul><li>defajkl</li></ul>"
+[PASS] TypingA at "<p>abc[</p><p>}<br></p>" - comparing innerHTML
+[PASS] TypingA at "<p>abc[<span contenteditable="false">def</span>]ghi</p>" - comparing innerHTML
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>d]ef</td></tr></table>" - comparing innerHTML
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>def</td></tr><tr><td>ghi</td><td>j]kl</td></tr></table>" - comparing innerHTML
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>def</td></tr></table><table><tr><td>ghi</td><td>j]kl</td></tr></table>" - comparing innerHTML
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-get-target-ranges-non-collapsed-selection.tentative_TypingA-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-get-target-ranges-non-collapsed-selection.tentative_TypingA-expected.txt
new file mode 100644
index 0000000..cc1168a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-get-target-ranges-non-collapsed-selection.tentative_TypingA-expected.txt
@@ -0,0 +1,103 @@
+This is a testharness.js-based test.
+Found 70 tests; 40 PASS, 30 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] TypingA at "<p>{abc}</p>"
+[PASS] TypingA at "<p>{abc}<br></p>"
+[PASS] TypingA at "<p>{<img>}</p>"
+[PASS] TypingA at "<p>{<img>}<br></p>"
+[FAIL] TypingA at "<p>{ abc }</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \" a \", 0) - (#text \" a \", 5)" but got "(#text \" a \", 1) - (#text \" a \", 4)"
+[FAIL] TypingA at "<p>abc   [</p><p>]   def</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 3)" but got "(#text \"abcadef\", 6) - (<p>, 0)"
+[PASS] TypingA at "<p>ab[c</p><p>d]ef</p>"
+[PASS] TypingA at "<p>ab[c </p><p> d]ef</p>"
+[FAIL] TypingA at "<p>ab[c </p><p>] def</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abadef\", 2) - (#text \"\", 1)" but got "(#text \"abadef\", 2) - (<p>, 0)"
+[FAIL] TypingA at "<p>abc [</p><p>] def</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 1)" but got "(#text \"abcadef\", 4) - (<p>, 0)"
+[FAIL] TypingA at "<p>abc [</p><p> ]def</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 1)" but got "(#text \"abcadef\", 4) - (<p>, 0)"
+[FAIL] TypingA at "<p>abc[<img>]def</p>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abca\", 3) - (#text \"def\", 0)" but got "(<p>, 1) - (<p>, 2)"
+[PASS] TypingA at "<div>abc[<hr>]def</div>"
+[FAIL] TypingA at "<div>abc [<hr>]def</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abca\", 3) - (#text \"def\", 0)" but got "(#text \"abca\", 4) - (#text \"def\", 0)"
+[FAIL] TypingA at "<div>abc [<hr>] def</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abca\", 3) - (#text \"def\", 1)" but got "(#text \"abca\", 4) - (#text \"def\", 0)"
+[FAIL] TypingA at "<div>abc {<hr>} def</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abca\", 3) - (#text \"def\", 1)" but got "(#text \"abca\", 4) - (#text \"def\", 0)"
+[PASS] TypingA at "<p>abc{<br>}def</p>"
+[FAIL] TypingA at "<div>abc[<p>]def<br>ghi</p></div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 0)" but got "(#text \"abcadef\", 3) - (<p>, 0)"
+[FAIL] TypingA at "<div>abc   [<p>]   def<br>ghi</p></div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 3)" but got "(#text \"abcadef\", 6) - (<p>, 0)"
+[PASS] TypingA at "<div><p>abc[</p>]def</div>"
+[FAIL] TypingA at "<div><p>abc   [</p>]   def</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 3)" but got "(#text \"abcadef\", 6) - (#text \"\", 0)"
+[FAIL] TypingA at "<div>abc[<ul><li>]def</li></ul>ghi</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 0)" but got "(#text \"abcadef\", 3) - (<li>, 0)"
+[FAIL] TypingA at "<div>abc  [<ul><li>] def </li></ul>  ghi</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 1)" but got "(#text \"abcadef\", 5) - (<li>, 0)"
+[PASS] TypingA at "<div>abc<ul><li>def[</li></ul>]ghi</div>"
+[FAIL] TypingA at "<div>abc <ul><li>  def  [</li></ul>] ghi</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"  defaghi\", 5) - (#text \"\", 1)" but got "(#text \"  defaghi\", 7) - (#text \"\", 0)"
+[FAIL] TypingA at "<div>abc[<ul><li>]def</li><li>ghi</li></ul>jkl</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcadef\", 3) - (#text \"\", 0)" but got "(#text \"abcadef\", 3) - (<li>, 0)"
+[FAIL] TypingA at "<div>abc[<ul><li>def</li><li>]ghi</li></ul>jkl</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"abcaghi\", 3) - (#text \"\", 0)" but got "(#text \"abcaghi\", 3) - (<li>, 0)"
+[FAIL] TypingA at "<div>abc<ul><li>def[</li><li>]ghi</li></ul>jkl</div>"
+  assert_equals: gBeforeinput[0].getTargetRanges()[0] should return expected range (inputType is "insertText") expected "(#text \"defaghi\", 3) - (#text \"\", 0)" but got "(#text \"defaghi\", 3) - (<li>, 0)"
+[PASS] TypingA at "<div>abc<ul><li>def</li><li>ghi[</li></ul>]jkl</div>"
+[PASS] TypingA at "<div>abc<ul><li>def[</li><li>ghi</li></ul>]jkl</div>"
+[PASS] TypingA at "<p>abc[</p><p>}<br></p>"
+[PASS] TypingA at "<p>abc[<span contenteditable="false">def</span>]ghi</p>"
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>d]ef</td></tr></table>"
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>def</td></tr><tr><td>ghi</td><td>j]kl</td></tr></table>"
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>def</td></tr></table><table><tr><td>ghi</td><td>j]kl</td></tr></table>"
+[PASS] TypingA at "<p>{abc}</p>" - comparing innerHTML
+[PASS] TypingA at "<p>{abc}<br></p>" - comparing innerHTML
+[PASS] TypingA at "<p>{<img>}</p>" - comparing innerHTML
+[PASS] TypingA at "<p>{<img>}<br></p>" - comparing innerHTML
+[FAIL] TypingA at "<p>{ abc }</p>" - comparing innerHTML
+  assert_equals: expected "<p>a</p>" but got "<p> a </p>"
+[PASS] TypingA at "<p>abc   [</p><p>]   def</p>" - comparing innerHTML
+[PASS] TypingA at "<p>ab[c</p><p>d]ef</p>" - comparing innerHTML
+[PASS] TypingA at "<p>ab[c </p><p> d]ef</p>" - comparing innerHTML
+[PASS] TypingA at "<p>ab[c </p><p>] def</p>" - comparing innerHTML
+[PASS] TypingA at "<p>abc [</p><p>] def</p>" - comparing innerHTML
+[PASS] TypingA at "<p>abc [</p><p> ]def</p>" - comparing innerHTML
+[PASS] TypingA at "<p>abc[<img>]def</p>" - comparing innerHTML
+[PASS] TypingA at "<div>abc[<hr>]def</div>" - comparing innerHTML
+[PASS] TypingA at "<div>abc [<hr>]def</div>" - comparing innerHTML
+[PASS] TypingA at "<div>abc [<hr>] def</div>" - comparing innerHTML
+[PASS] TypingA at "<div>abc {<hr>} def</div>" - comparing innerHTML
+[PASS] TypingA at "<p>abc{<br>}def</p>" - comparing innerHTML
+[PASS] TypingA at "<div>abc[<p>]def<br>ghi</p></div>" - comparing innerHTML
+[PASS] TypingA at "<div>abc   [<p>]   def<br>ghi</p></div>" - comparing innerHTML
+[FAIL] TypingA at "<div><p>abc[</p>]def</div>" - comparing innerHTML
+  assert_in_array: value "<p>abcadef</p>" not in array ["<div><p>abcadef</p></div>", "<div><p>abcadef<br></p></div>"]
+[FAIL] TypingA at "<div><p>abc   [</p>]   def</div>" - comparing innerHTML
+  assert_in_array: value "<p>abcadef</p>" not in array ["<div><p>abcadef</p></div>", "<div><p>abcadef<br></p></div>"]
+[FAIL] TypingA at "<div>abc[<ul><li>]def</li></ul>ghi</div>" - comparing innerHTML
+  assert_equals: expected "<div>abcadefghi</div>" but got "abcadefghi<br>"
+[FAIL] TypingA at "<div>abc  [<ul><li>] def </li></ul>  ghi</div>" - comparing innerHTML
+  assert_equals: expected "<div>abcadefghi</div>" but got "abcadef&nbsp; ghi<br>"
+[FAIL] TypingA at "<div>abc<ul><li>def[</li></ul>]ghi</div>" - comparing innerHTML
+  assert_equals: expected "<div>abc<ul><li>defaghi</li></ul></div>" but got "abc<ul><li>defaghi</li></ul>"
+[FAIL] TypingA at "<div>abc <ul><li>  def  [</li></ul>] ghi</div>" - comparing innerHTML
+  assert_in_array: value "abc <ul><li>  defaghi</li></ul>" not in array ["<div>abc <ul><li>  defaghi</li></ul></div>", "<div>abc <ul><li>defaghi</li></ul></div>", "<div>abc<ul><li>defaghi</li></ul></div>"]
+[FAIL] TypingA at "<div>abc[<ul><li>]def</li><li>ghi</li></ul>jkl</div>" - comparing innerHTML
+  assert_equals: expected "<div>abcadef<ul><li>ghi</li></ul>jkl</div>" but got "abcadef<ul><li>ghi</li></ul>jkl<br>"
+[FAIL] TypingA at "<div>abc[<ul><li>def</li><li>]ghi</li></ul>jkl</div>" - comparing innerHTML
+  assert_in_array: value "abcaghijkl<br>" not in array ["<div>abcaghijkl</div>", "<div>abcaghijkl<br></div>"]
+[FAIL] TypingA at "<div>abc<ul><li>def[</li><li>]ghi</li></ul>jkl</div>" - comparing innerHTML
+  assert_equals: expected "<div>abc<ul><li>defaghi</li></ul>jkl</div>" but got "abc<ul><li>defaghi</li></ul>jkl<br>"
+[FAIL] TypingA at "<div>abc<ul><li>def</li><li>ghi[</li></ul>]jkl</div>" - comparing innerHTML
+  assert_equals: expected "<div>abc<ul><li>def</li><li>ghiajkl</li></ul></div>" but got "abc<ul><li>def</li><li>ghiajkl</li></ul>"
+[FAIL] TypingA at "<div>abc<ul><li>def[</li><li>ghi</li></ul>]jkl</div>" - comparing innerHTML
+  assert_equals: expected "<div>abc<ul><li>defajkl</li></ul></div>" but got "abc<ul><li>defajkl</li></ul>"
+[PASS] TypingA at "<p>abc[</p><p>}<br></p>" - comparing innerHTML
+[PASS] TypingA at "<p>abc[<span contenteditable="false">def</span>]ghi</p>" - comparing innerHTML
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>d]ef</td></tr></table>" - comparing innerHTML
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>def</td></tr><tr><td>ghi</td><td>j]kl</td></tr></table>" - comparing innerHTML
+[PASS] TypingA at "<table><tr><td>ab[c</td><td>def</td></tr></table><table><tr><td>ghi</td><td>j]kl</td></tr></table>" - comparing innerHTML
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-typing-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-typing-expected.txt
new file mode 100644
index 0000000..cfda921
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/input-events/input-events-typing-expected.txt
@@ -0,0 +1,14 @@
+This is a testharness.js-based test.
+[PASS] It triggers beforeinput and input events on text typing
+[PASS] It triggers beforeinput and input events on typing RETURN
+[PASS] It triggers beforeinput and input events on typing Shift+RETURN
+[PASS] It triggers beforeinput and input events on typing DELETE with pre-existing content
+[FAIL] It triggers beforeinput and input events on typing DELETE with no pre-existing content
+  assert_equals: expected 2 but got 1
+[PASS] It triggers beforeinput and input events on typing BACK_SPACE with pre-existing content
+[FAIL] It triggers beforeinput and input events on typing BACK_SPACE with no pre-existing content
+  assert_equals: expected 2 but got 1
+[PASS] It triggers beforeinput and input events on typing Undo and Redo key combinations with an existing history
+[PASS] It triggers beforeinput and input events on typing Undo and Redo key combinations without an existing history
+[PASS] InputEvents have correct data/order when typing on textarea and contenteditable
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/long-animation-frame/tentative/loaf-desired-exec-time-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/long-animation-frame/tentative/loaf-desired-exec-time-expected.txt
new file mode 100644
index 0000000..b6de5414
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/long-animation-frame/tentative/loaf-desired-exec-time-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[FAIL] event-listener entries desiredExecutionStart is the eventTimestamp
+  promise_test: Unhandled rejection with value: object "Error: Tried to run in a non-testharness window without a call to set_test_context"
+[PASS] desiredExecutionStart for setTimeout should be the setup time + delay
+[PASS] desiredExecutionStart for Scheduler.postTask should be the time it was called
+[PASS] desiredExecutionStart & desiredRenderStart for requestAnimationFrame should be the same as the rAF argument
+[PASS] desiredRenderStart and renderStart should reflect main thread delays
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/long-animation-frame/tentative/loaf-visibility-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/long-animation-frame/tentative/loaf-visibility-expected.txt
new file mode 100644
index 0000000..bd10119
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/long-animation-frame/tentative/loaf-visibility-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Consistently creates long frame
+[PASS] Invisible windows do not report long animation frames
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/mathml/presentation-markup/tables/table-default-styles-001-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/mathml/presentation-markup/tables/table-default-styles-001-expected.txt
new file mode 100644
index 0000000..a352602
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/mathml/presentation-markup/tables/table-default-styles-001-expected.txt
@@ -0,0 +1,17 @@
+This is a testharness.js-based test.
+[PASS] Default math-style value on mtable
+[FAIL] Default display value on mtable
+  assert_equals: expected "inline-table" but got "table"
+[PASS] Default display value on mtr
+[PASS] Default display value on mtd
+[FAIL] Default text-align value on mtd
+  assert_equals: expected "center" but got "-webkit-center"
+[PASS] Default padding-left value on mtd
+[PASS] Default padding-right value on mtd
+[FAIL] Default padding-top value on mtd
+  assert_equals: expected "10px" but got "6px"
+[FAIL] Default padding-bottom value on mtd
+  assert_equals: expected "10px" but got "6px"
+[FAIL] Bounding box is the same as mrow + mtd default padding
+  assert_equals: expected 30 but got 22
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/defaultPrevented-window-stop-after-dispatch-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/defaultPrevented-window-stop-after-dispatch-expected.txt
new file mode 100644
index 0000000..e2983b9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/defaultPrevented-window-stop-after-dispatch-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Navigation was aborted
+[PASS] window.stop() doesn't affect navigateEvent.defaultPrevented after dispatch
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/navigation-traverseTo-same-document-preventDefault-multiple-windows-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/navigation-traverseTo-same-document-preventDefault-multiple-windows-expected.txt
new file mode 100644
index 0000000..e812dbf
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/navigation-traverseTo-same-document-preventDefault-multiple-windows-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Navigation was aborted
+[PASS] navigation.traverseTo() - if a top window cancels the traversal, any iframes should not fire navigate
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/signal-abort-window-stop-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/signal-abort-window-stop-expected.txt
new file mode 100644
index 0000000..a0d8b1d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/signal-abort-window-stop-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Navigation was aborted
+[PASS] window.stop() signals event.signal
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/signal-abort-window-stop-in-onnavigate-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/signal-abort-window-stop-in-onnavigate-expected.txt
new file mode 100644
index 0000000..4f3b712
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigate-event/signal-abort-window-stop-in-onnavigate-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Navigation was aborted
+[PASS] window.stop() signals event.signal inside a navigate event handler
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigation-history-entry/entries-after-bfcache-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigation-history-entry/entries-after-bfcache-expected.txt
new file mode 100644
index 0000000..fa1c799
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigation-history-entry/entries-after-bfcache-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] entries() must contain the forward-history page after navigating back to a bfcached page
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigation-history-entry/entries-after-bfcache-in-iframe-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigation-history-entry/entries-after-bfcache-in-iframe-expected.txt
new file mode 100644
index 0000000..f6292667
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/navigation-history-entry/entries-after-bfcache-in-iframe-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] entries() in an iframe must be updated after navigating back to a bfcached page
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/per-entry-events/dispose-after-bfcache-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/per-entry-events/dispose-after-bfcache-expected.txt
new file mode 100644
index 0000000..fa1c799
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/per-entry-events/dispose-after-bfcache-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] entries() must contain the forward-history page after navigating back to a bfcached page
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/scroll-behavior/scroll-after-preventDefault-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/scroll-behavior/scroll-after-preventDefault-expected.txt
new file mode 100644
index 0000000..69beb2b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/navigation-api/scroll-behavior/scroll-after-preventDefault-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Navigation was aborted
+[PASS] scroll: scroll() should throw after preventDefault
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-404.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-404.https-expected.txt
new file mode 100644
index 0000000..c164104d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-404.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] \n    Test that NEL reports are sent for HTTP errors\n  
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-cache-validation.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-cache-validation.https-expected.txt
new file mode 100644
index 0000000..b5811e0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-cache-validation.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] \n    Test that NEL reports are sent for cache validation requests\n  
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-redirect.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-redirect.https-expected.txt
new file mode 100644
index 0000000..1eefe154
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-redirect.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] \n    Test that NEL reports are sent for redirects\n  
+  assert_true: receive report about redirected resource expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-subdomain-dns-failure.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-subdomain-dns-failure.https-expected.txt
new file mode 100644
index 0000000..2d2f97b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-subdomain-dns-failure.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] \n    Test that include_subdomains policies report DNS failures for subdomains\n  
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-success-with-subdomain-policy.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-success-with-subdomain-policy.https-expected.txt
new file mode 100644
index 0000000..028d4d5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-success-with-subdomain-policy.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] \n    Test that NEL reports are sent for successful requests\n  
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-success.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-success.https-expected.txt
new file mode 100644
index 0000000..028d4d5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/network-error-logging/sends-report-on-success.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] \n    Test that NEL reports are sent for successful requests\n  
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/notifications/permissions-non-secure-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/notifications/permissions-non-secure-expected.txt
new file mode 100644
index 0000000..414283bf
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/notifications/permissions-non-secure-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Notification.requestPermission must be called from a secure context
+  assert_equals: expected "denied" but got "default"
+[PASS] Notification.permission must be called from a secure context
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/notifications/shownotification.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/notifications/shownotification.https.window-expected.txt
new file mode 100644
index 0000000..62631d6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/notifications/shownotification.https.window-expected.txt
@@ -0,0 +1,15 @@
+This is a testharness.js-based test.
+[PASS] fetching no notifications
+[FAIL] fetching notification with an empty title
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'showNotification' on 'ServiceWorkerRegistration': No notification permission has been granted for this origin."
+[FAIL] fetching notification by tag filter
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'showNotification' on 'ServiceWorkerRegistration': No notification permission has been granted for this origin."
+[FAIL] fetching multiple notifications
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'showNotification' on 'ServiceWorkerRegistration': No notification permission has been granted for this origin."
+[FAIL] fetching from another registration
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'showNotification' on 'ServiceWorkerRegistration': No notification permission has been granted for this origin."
+[FAIL] fetching only persistent notifications
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'showNotification' on 'ServiceWorkerRegistration': No notification permission has been granted for this origin."
+[FAIL] fetching a notification with custom data
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'showNotification' on 'ServiceWorkerRegistration': No notification permission has been granted for this origin."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-event/motion/page-visibility.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-event/motion/page-visibility.https-expected.txt
new file mode 100644
index 0000000..5eb7f93
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-event/motion/page-visibility.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Tests to check that devicemotion events are not fired when the page is not visible.
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-event/orientation/page-visibility.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-event/orientation/page-visibility.https-expected.txt
new file mode 100644
index 0000000..554410c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-event/orientation/page-visibility.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Tests to check that deviceorientation events are not fired when the page is not visible.
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/AbsoluteOrientationSensor-iframe-access.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/AbsoluteOrientationSensor-iframe-access.https-expected.txt
new file mode 100644
index 0000000..2d946ea
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/AbsoluteOrientationSensor-iframe-access.https-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[FAIL] AbsoluteOrientationSensor: unfocused sensors in cross-origin frames are not updated
+  promise_test: Unhandled rejection with value: "NotAllowedError: Permissions to access sensor are not granted"
+[PASS] AbsoluteOrientationSensor: sensors in same-origin frames are updated if one of the frames is focused
+[PASS] AbsoluteOrientationSensor: losing a document's frame with an active sensor does not crash
+[PASS] AbsoluteOrientationSensor: calling start() in a non-fully active document does not crash
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/AbsoluteOrientationSensor.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/AbsoluteOrientationSensor.https-expected.txt
new file mode 100644
index 0000000..729fe50
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/AbsoluteOrientationSensor.https-expected.txt
@@ -0,0 +1,24 @@
+This is a testharness.js-based test.
+[PASS] AbsoluteOrientationSensor: Test that onerror is sent when permissions are not granted.
+[PASS] AbsoluteOrientationSensor: Test that onerror is send when start() call has failed.
+[PASS] AbsoluteOrientationSensor: Test that frequency is capped to allowed maximum.
+[PASS] AbsoluteOrientationSensor: Test that frequency is capped to the maximum supported frequency.
+[PASS] AbsoluteOrientationSensor: Test that frequency is limited to the minimum supported frequency.
+[PASS] AbsoluteOrientationSensor: Test that sensor cannot be constructed within iframe disallowed to use feature policy.
+[PASS] AbsoluteOrientationSensor: Test that sensor can be constructed within an iframe allowed to use feature policy.
+[PASS] AbsoluteOrientationSensor: Test that 'onreading' is called and sensor reading is valid.
+[PASS] AbsoluteOrientationSensor: sensor reading is correct.
+[PASS] AbsoluteOrientationSensor: Test that readings are all mapped to expectedReadings correctly.
+[PASS] AbsoluteOrientationSensor: sensor timestamp is updated when time passes.
+[PASS] AbsoluteOrientationSensor: Test that sensor can be successfully created and its states are correct.
+[PASS] AbsoluteOrientationSensor: no exception is thrown when calling start() on already started sensor.
+[PASS] AbsoluteOrientationSensor: no exception is thrown when calling stop() on already stopped sensor.
+[PASS] AbsoluteOrientationSensor: Test that fresh reading is fetched on start().
+[FAIL] AbsoluteOrientationSensor: Readings are not delivered when the page has no visibility
+  assert_true: expected true got false
+[PASS] AbsoluteOrientationSensor: frequency hint works.
+[PASS] AbsoluteOrientationSensor: Readings delivered by shared platform sensor are immediately accessible to all sensors.
+[PASS] AbsoluteOrientationSensor: throw 'TypeError' if frequency is invalid.
+[PASS] AbsoluteOrientationSensor.quaternion return a four-element FrozenArray.
+[PASS] AbsoluteOrientationSensor.populateMatrix() method works correctly.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/RelativeOrientationSensor-iframe-access.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/RelativeOrientationSensor-iframe-access.https-expected.txt
new file mode 100644
index 0000000..54d92c6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/RelativeOrientationSensor-iframe-access.https-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[FAIL] RelativeOrientationSensor: unfocused sensors in cross-origin frames are not updated
+  promise_test: Unhandled rejection with value: "NotAllowedError: Permissions to access sensor are not granted"
+[PASS] RelativeOrientationSensor: sensors in same-origin frames are updated if one of the frames is focused
+[PASS] RelativeOrientationSensor: losing a document's frame with an active sensor does not crash
+[PASS] RelativeOrientationSensor: calling start() in a non-fully active document does not crash
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/RelativeOrientationSensor.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/RelativeOrientationSensor.https-expected.txt
new file mode 100644
index 0000000..51e207e8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/orientation-sensor/RelativeOrientationSensor.https-expected.txt
@@ -0,0 +1,24 @@
+This is a testharness.js-based test.
+[PASS] RelativeOrientationSensor: Test that onerror is sent when permissions are not granted.
+[PASS] RelativeOrientationSensor: Test that onerror is send when start() call has failed.
+[PASS] RelativeOrientationSensor: Test that frequency is capped to allowed maximum.
+[PASS] RelativeOrientationSensor: Test that frequency is capped to the maximum supported frequency.
+[PASS] RelativeOrientationSensor: Test that frequency is limited to the minimum supported frequency.
+[PASS] RelativeOrientationSensor: Test that sensor cannot be constructed within iframe disallowed to use feature policy.
+[PASS] RelativeOrientationSensor: Test that sensor can be constructed within an iframe allowed to use feature policy.
+[PASS] RelativeOrientationSensor: Test that 'onreading' is called and sensor reading is valid.
+[PASS] RelativeOrientationSensor: sensor reading is correct.
+[PASS] RelativeOrientationSensor: Test that readings are all mapped to expectedReadings correctly.
+[PASS] RelativeOrientationSensor: sensor timestamp is updated when time passes.
+[PASS] RelativeOrientationSensor: Test that sensor can be successfully created and its states are correct.
+[PASS] RelativeOrientationSensor: no exception is thrown when calling start() on already started sensor.
+[PASS] RelativeOrientationSensor: no exception is thrown when calling stop() on already stopped sensor.
+[PASS] RelativeOrientationSensor: Test that fresh reading is fetched on start().
+[FAIL] RelativeOrientationSensor: Readings are not delivered when the page has no visibility
+  assert_true: expected true got false
+[PASS] RelativeOrientationSensor: frequency hint works.
+[PASS] RelativeOrientationSensor: Readings delivered by shared platform sensor are immediately accessible to all sensors.
+[PASS] RelativeOrientationSensor: throw 'TypeError' if frequency is invalid.
+[PASS] RelativeOrientationSensor.quaternion return a four-element FrozenArray.
+[PASS] RelativeOrientationSensor.populateMatrix() method works correctly.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/page-visibility/minimize-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/page-visibility/minimize-expected.txt
new file mode 100644
index 0000000..7239203
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/page-visibility/minimize-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[FAIL] visibilityState & hidden should be affected by window being minimized/restored
+  assert_equals: expected "hidden" but got "visible"
+[FAIL] visibilitychange event should be fired when minimized/restored
+  assert_array_equals: lengths differ, expected array ["hidden", "visible"] length 2, got [] length 0
+[FAIL] iframe should receive visibility events when top level window is shown/hidden
+  assert_array_equals: lengths differ, expected array ["hidden", "visible"] length 2, got [] length 0
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/payment-request/show-consume-activation.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/payment-request/show-consume-activation.https-expected.txt
new file mode 100644
index 0000000..8136cc5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/payment-request/show-consume-activation.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Failed to execute 'show' on 'PaymentRequest': Already called show() once
+[FAIL] Calling show consumes user activation, if present
+  assert_false: expected false got true
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-attributes.tentative.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-attributes.tentative.window-expected.txt
new file mode 100644
index 0000000..22b46fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-attributes.tentative.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] RemoteContextHelper navigation using BFCache
+  assert_true: Expected: websocket\nGot: internal-error,websocket\nMissing: \nExtra: internal-error\n expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.tentative.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.tentative.window-expected.txt
new file mode 100644
index 0000000..22b46fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.tentative.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] RemoteContextHelper navigation using BFCache
+  assert_true: Expected: websocket\nGot: internal-error,websocket\nMissing: \nExtra: internal-error\n expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache.tentative.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache.tentative.window-expected.txt
new file mode 100644
index 0000000..4e7a4a7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache.tentative.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] RemoteContextHelper navigation using BFCache
+  BFCache not supported.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.tentative.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.tentative.window-expected.txt
new file mode 100644
index 0000000..a95e280
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.tentative.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] RemoteContextHelper navigation using BFCache
+  assert_equals: expected "no" but got "yes"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-fetch.tentative.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-fetch.tentative.window-expected.txt
new file mode 100644
index 0000000..7d453a9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-fetch.tentative.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Ensure that ongoing fetch upon entering bfcache blocks bfcache and recorded.
+  assert_true: Expected: fetch\nGot: internal-error\nMissing: fetch\nExtra: internal-error\n expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.tentative.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.tentative.window-expected.txt
new file mode 100644
index 0000000..22b46fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.tentative.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] RemoteContextHelper navigation using BFCache
+  assert_true: Expected: websocket\nGot: internal-error,websocket\nMissing: \nExtra: internal-error\n expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-reload.tentative.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-reload.tentative.window-expected.txt
new file mode 100644
index 0000000..22b46fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-reload.tentative.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] RemoteContextHelper navigation using BFCache
+  assert_true: Expected: websocket\nGot: internal-error,websocket\nMissing: \nExtra: internal-error\n expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-replace.tentative.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-replace.tentative.window-expected.txt
new file mode 100644
index 0000000..22b46fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-replace.tentative.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] RemoteContextHelper navigation using BFCache
+  assert_true: Expected: websocket\nGot: internal-error,websocket\nMissing: \nExtra: internal-error\n expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub-expected.txt
new file mode 100644
index 0000000..e85b9c3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] bluetooth-allowed-by-permissions-policy-attribute-redirect-on-load
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: https://web-platform.test:8444/gen/content/web_test/common/fake_bluetooth_chooser.mojom.m.js"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-allowed-by-permissions-policy-attribute.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-allowed-by-permissions-policy-attribute.https.sub-expected.txt
new file mode 100644
index 0000000..344c664
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-allowed-by-permissions-policy-attribute.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] bluetooth-allowed-by-permissions-policy-attribute
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: https://web-platform.test:8444/gen/content/web_test/common/fake_bluetooth_chooser.mojom.m.js"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-allowed-by-permissions-policy.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-allowed-by-permissions-policy.https.sub-expected.txt
new file mode 100644
index 0000000..c643f921
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-allowed-by-permissions-policy.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] bluetooth-allowed-by-permissions-policy
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: https://web-platform.test:8444/gen/content/web_test/common/fake_bluetooth_chooser.mojom.m.js"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-default-permissions-policy.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-default-permissions-policy.https.sub-expected.txt
new file mode 100644
index 0000000..387caf6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-default-permissions-policy.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] bluetooth-default-permissions-policy
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: https://web-platform.test:8444/gen/content/web_test/common/fake_bluetooth_chooser.mojom.m.js"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-disabled-by-permissions-policy.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-disabled-by-permissions-policy.https.sub-expected.txt
new file mode 100644
index 0000000..0e40824
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/bluetooth-disabled-by-permissions-policy.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] bluetooth-disabled-by-permissions-policy
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: https://web-platform.test:8444/gen/content/web_test/common/fake_bluetooth_chooser.mojom.m.js"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/reporting/bluetooth-report-only.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/reporting/bluetooth-report-only.https-expected.txt
new file mode 100644
index 0000000..acb45b3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/reporting/bluetooth-report-only.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] bluetooth-report-only
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: https://web-platform.test:8444/gen/content/web_test/common/fake_bluetooth_chooser.mojom.m.js"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/reporting/bluetooth-reporting.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/reporting/bluetooth-reporting.https-expected.txt
new file mode 100644
index 0000000..37a72efd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/reporting/bluetooth-reporting.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] bluetooth-reporting
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: https://web-platform.test:8444/gen/content/web_test/common/fake_bluetooth_chooser.mojom.m.js"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/reporting/picture-in-picture-report-only-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/reporting/picture-in-picture-report-only-expected.txt
new file mode 100644
index 0000000..649d5ea
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions-policy/reporting/picture-in-picture-report-only-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Picture-in-Picture report only mode
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions/permissions-query-feature-policy-attribute.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions/permissions-query-feature-policy-attribute.https.sub-expected.txt
new file mode 100644
index 0000000..bdf743c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/permissions/permissions-query-feature-policy-attribute.https.sub-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Permissions.state is "prompt" with allow="geolocation" in same-origin iframes.
+[PASS] Permissions.state is "prompt" with allow="geolocation" in cross-origin iframes.
+[PASS] Permission.state is "prompt" in same-origin iframes.
+[FAIL] Permission.state is "denied" in cross-origin iframes.
+  assert_equals: navigator.permissions.query("geolocation") expected "denied" but got "prompt"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/css-selector-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/css-selector-expected.txt
new file mode 100644
index 0000000..44795420
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/css-selector-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Entering and leaving Picture-in-Picture toggles CSS selector
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/disable-picture-in-picture-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/disable-picture-in-picture-expected.txt
new file mode 100644
index 0000000..f69e552
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/disable-picture-in-picture-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+[PASS] Test disablePictureInPicture IDL attribute
+[PASS] Request Picture-in-Picture rejects if disablePictureInPicture is true
+[FAIL] Request Picture-in-Picture rejects if disablePictureInPicture becomes true before promise resolves.
+  promise_rejects_dom: function "function() { throw e }" threw object "NotSupportedError: Picture-in-Picture is not available." that is not a DOMException InvalidStateError: property "code" is equal to 9, expected 11
+[FAIL] pictureInPictureElement is unset if disablePictureInPicture becomes true
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+[FAIL] pictureInPictureElement is unchanged if disablePictureInPicture becomes false
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+[FAIL] pictureInPictureElement is unchanged if disablePictureInPicture becomes true for another video
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/enter-picture-in-picture-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/enter-picture-in-picture-expected.txt
new file mode 100644
index 0000000..93af7542
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/enter-picture-in-picture-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test enterpictureinpicture event
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/exit-picture-in-picture-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/exit-picture-in-picture-expected.txt
new file mode 100644
index 0000000..0d4a409
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/exit-picture-in-picture-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Exit Picture-in-Picture resolves when there is a Picture-in-Picture video
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+[PASS] Exit Picture-in-Picture rejects when there is no Picture-in-Picture video
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/idlharness.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/idlharness.window-expected.txt
new file mode 100644
index 0000000..a72cfca
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/idlharness.window-expected.txt
@@ -0,0 +1,78 @@
+This is a testharness.js-based test.
+Found 66 tests; 57 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[FAIL] idl_test setup
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+[PASS] idl_test validation
+[PASS] Partial interface HTMLVideoElement: original interface defined
+[PASS] Partial interface HTMLVideoElement: member names are unique
+[PASS] Partial interface Document: original interface defined
+[PASS] Partial interface Document: member names are unique
+[PASS] Partial interface mixin DocumentOrShadowRoot: original interface mixin defined
+[PASS] Partial interface mixin DocumentOrShadowRoot: member names are unique
+[PASS] Partial interface Document[2]: member names are unique
+[PASS] Partial interface mixin DocumentOrShadowRoot[2]: member names are unique
+[PASS] Partial interface Document[3]: member names are unique
+[PASS] Document includes GlobalEventHandlers: member names are unique
+[PASS] HTMLElement includes GlobalEventHandlers: member names are unique
+[PASS] HTMLElement includes ElementContentEditable: member names are unique
+[PASS] HTMLElement includes HTMLOrSVGElement: member names are unique
+[PASS] Document includes NonElementParentNode: member names are unique
+[PASS] DocumentFragment includes NonElementParentNode: member names are unique
+[PASS] Document includes DocumentOrShadowRoot: member names are unique
+[PASS] ShadowRoot includes DocumentOrShadowRoot: member names are unique
+[PASS] Document includes ParentNode: member names are unique
+[PASS] DocumentFragment includes ParentNode: member names are unique
+[PASS] Element includes ParentNode: member names are unique
+[PASS] Element includes NonDocumentTypeChildNode: member names are unique
+[PASS] Element includes ChildNode: member names are unique
+[PASS] Element includes Slottable: member names are unique
+[PASS] Document includes XPathEvaluatorBase: member names are unique
+[PASS] PictureInPictureWindow interface: existence and properties of interface object
+[PASS] PictureInPictureWindow interface object length
+[PASS] PictureInPictureWindow interface object name
+[PASS] PictureInPictureWindow interface: existence and properties of interface prototype object
+[PASS] PictureInPictureWindow interface: existence and properties of interface prototype object's "constructor" property
+[PASS] PictureInPictureWindow interface: existence and properties of interface prototype object's @@unscopables property
+[PASS] PictureInPictureWindow interface: attribute width
+[PASS] PictureInPictureWindow interface: attribute height
+[PASS] PictureInPictureWindow interface: attribute onresize
+[FAIL] PictureInPictureWindow must be primary interface of pipw
+  assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: pipw is not defined"
+[FAIL] Stringification of pipw
+  assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: pipw is not defined"
+[FAIL] PictureInPictureWindow interface: pipw must inherit property "width" with the proper type
+  assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: pipw is not defined"
+[FAIL] PictureInPictureWindow interface: pipw must inherit property "height" with the proper type
+  assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: pipw is not defined"
+[FAIL] PictureInPictureWindow interface: pipw must inherit property "onresize" with the proper type
+  assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: pipw is not defined"
+[PASS] PictureInPictureEvent interface: existence and properties of interface object
+[PASS] PictureInPictureEvent interface object length
+[PASS] PictureInPictureEvent interface object name
+[PASS] PictureInPictureEvent interface: existence and properties of interface prototype object
+[PASS] PictureInPictureEvent interface: existence and properties of interface prototype object's "constructor" property
+[PASS] PictureInPictureEvent interface: existence and properties of interface prototype object's @@unscopables property
+[PASS] PictureInPictureEvent interface: attribute pictureInPictureWindow
+[FAIL] PictureInPictureEvent must be primary interface of new PictureInPictureEvent("type", { pictureInPictureWindow: pipw })
+  assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: pipw is not defined"
+[FAIL] Stringification of new PictureInPictureEvent("type", { pictureInPictureWindow: pipw })
+  assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: pipw is not defined"
+[FAIL] PictureInPictureEvent interface: new PictureInPictureEvent("type", { pictureInPictureWindow: pipw }) must inherit property "pictureInPictureWindow" with the proper type
+  assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: pipw is not defined"
+[PASS] HTMLVideoElement interface: operation requestPictureInPicture()
+[PASS] HTMLVideoElement interface: attribute onenterpictureinpicture
+[PASS] HTMLVideoElement interface: attribute onleavepictureinpicture
+[PASS] HTMLVideoElement interface: attribute disablePictureInPicture
+[PASS] HTMLVideoElement interface: video must inherit property "requestPictureInPicture()" with the proper type
+[PASS] HTMLVideoElement interface: video must inherit property "onenterpictureinpicture" with the proper type
+[PASS] HTMLVideoElement interface: video must inherit property "onleavepictureinpicture" with the proper type
+[PASS] HTMLVideoElement interface: video must inherit property "disablePictureInPicture" with the proper type
+[PASS] DocumentOrShadowRoot interface: document must inherit property "pictureInPictureElement" with the proper type
+[PASS] Document interface: attribute pictureInPictureEnabled
+[PASS] Document interface: operation exitPictureInPicture()
+[PASS] Document interface: attribute pictureInPictureElement
+[PASS] Document interface: document must inherit property "pictureInPictureEnabled" with the proper type
+[PASS] Document interface: document must inherit property "exitPictureInPicture()" with the proper type
+[PASS] Document interface: document must inherit property "pictureInPictureElement" with the proper type
+[PASS] ShadowRoot interface: attribute pictureInPictureElement
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/leave-picture-in-picture-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/leave-picture-in-picture-expected.txt
new file mode 100644
index 0000000..08bff12
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/leave-picture-in-picture-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] leavepictureinpicture event is fired if document.exitPictureInPicture
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+[FAIL] leavepictureinpicture event is fired if video.disablePictureInPicture is set to true
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/mediastream-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/mediastream-expected.txt
new file mode 100644
index 0000000..6752f2c3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/mediastream-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] request Picture-in-Picture resolves on user click with Picture-in-Picture window
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/picture-in-picture-element-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/picture-in-picture-element-expected.txt
new file mode 100644
index 0000000..dd19b9c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/picture-in-picture-element-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test Picture-in-Picture element
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/picture-in-picture-window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/picture-in-picture-window-expected.txt
new file mode 100644
index 0000000..01f2ba1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/picture-in-picture-window-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+[FAIL] Picture-in-Picture window dimensions are set after entering Picture-in-Picture
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+[FAIL] Picture-in-Picture window dimensions are set to 0 after entering Picture-in-Picture for another video
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+[FAIL] Picture-in-Picture window is unchanged after entering Picture-in-Picture for video already in Picture-in-Picture
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+[FAIL] Picture-in-Picture window dimensions are set to 0 after exiting Picture-in-Picture
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+[FAIL] Picture-in-Picture window dimensions are set to 0 if disablePictureInPicture becomes true
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/removed-from-document-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/removed-from-document-expected.txt
new file mode 100644
index 0000000..8e4479c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/removed-from-document-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Picture-in-Picture video does not pause when removed from document
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/request-picture-in-picture-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/request-picture-in-picture-expected.txt
new file mode 100644
index 0000000..aa8cd9a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/request-picture-in-picture-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] request Picture-in-Picture requires a user gesture
+[PASS] request Picture-in-Picture requires loaded metadata for the video element
+[PASS] request Picture-in-Picture requires video track for the video element
+[FAIL] request Picture-in-Picture resolves on user click
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/request-picture-in-picture-twice-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/request-picture-in-picture-twice-expected.txt
new file mode 100644
index 0000000..31bb29b2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/request-picture-in-picture-twice-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] request Picture-in-Picture consumes user gesture
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+[FAIL] request Picture-in-Picture does not require user gesture if document.pictureInPictureElement is set
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/shadow-dom-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/shadow-dom-expected.txt
new file mode 100644
index 0000000..64823c0b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/picture-in-picture/shadow-dom-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test for Picture-In-Picture and Shadow DOM
+  promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https-expected.txt
new file mode 100644
index 0000000..7314e32
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Coalesced pointermoves under load
+  assert_true: Coalesed pointermoves received expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https_mouse-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https_mouse-expected.txt
new file mode 100644
index 0000000..7314e32
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https_mouse-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Coalesced pointermoves under load
+  assert_true: Coalesed pointermoves received expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https_pen-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https_pen-expected.txt
new file mode 100644
index 0000000..7314e32
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https_pen-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Coalesced pointermoves under load
+  assert_true: Coalesed pointermoves received expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https_touch-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https_touch-expected.txt
new file mode 100644
index 0000000..7314e32
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/coalesced_events_attributes_under_load.https_touch-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Coalesced pointermoves under load
+  assert_true: Coalesed pointermoves received expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-expected.txt
new file mode 100644
index 0000000..aa27b6fb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: detected_pointertypes is not defined
+[PASS] touch-action attribute test
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/pointerevent_touch-action-modified_touch-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/pointerevent_touch-action-modified_touch-expected.txt
new file mode 100644
index 0000000..ddd2441
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/pointerevents/pointerevent_touch-action-modified_touch-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Deleting touch-action elem after pointerdown
+  promise_test: Unhandled rejection with value: "error: Action action_sequence failed"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/preload/prefetch-document-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/preload/prefetch-document-expected.txt
new file mode 100644
index 0000000..a148644
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/preload/prefetch-document-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+[PASS] same origin document prefetch without 'as' should be consumed
+[PASS] same-site different-origin document prefetch without 'as' should be consumed
+[FAIL] different-site document prefetch without 'as' should not be consumed
+  assert_equals: expected 2 but got 1
+[FAIL] different-site document prefetch with 'as=document' should not be consumed
+  assert_equals: expected 2 but got 1
+[PASS] Document prefetch should send the exact Accept header as navigation
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/cross-origin-report-no-credentials.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/cross-origin-report-no-credentials.https.sub-expected.txt
new file mode 100644
index 0000000..3eab6fb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/cross-origin-report-no-credentials.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Reporting endpoints did not receive credentials.
+  assert_unreached: A report of csp-violation from https://web-platform.test:8444/reporting/cross-origin-report-no-credentials.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/cross-origin-reports-isolated.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/cross-origin-reports-isolated.https.sub-expected.txt
new file mode 100644
index 0000000..dbd0e53
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/cross-origin-reports-isolated.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Reports were sent in two requests.
+  assert_equals: expected 2 but got 0
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/cross-origin-same-site-credentials.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/cross-origin-same-site-credentials.https.sub-expected.txt
new file mode 100644
index 0000000..1deec0f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/cross-origin-same-site-credentials.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Reporting endpoints received credentials.
+  assert_unreached: A report of csp-violation from https://www.web-platform.test:8444/reporting/resources/same-origin-report.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-bypass-report-to.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-bypass-report-to.https.sub-expected.txt
new file mode 100644
index 0000000..a0943cf4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-bypass-report-to.https.sub-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[PASS] document policy violation observed
+[FAIL] Only the Reporting-Endpoints configured endpoint received reports.
+  assert_unreached: A report of document-policy-violation from https://web-platform.test:8444/reporting/document-reporting-bypass-report-to.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-default-endpoint.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-default-endpoint.https.sub-expected.txt
new file mode 100644
index 0000000..fee0db8c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-default-endpoint.https.sub-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[PASS] report generated
+[FAIL] Reporting-Endpoints defined endpoint received reports.
+  assert_unreached: A report of deprecation from https://web-platform.test:8444/reporting/document-reporting-default-endpoint.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-destroy-after-document-close.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-destroy-after-document-close.https.sub-expected.txt
new file mode 100644
index 0000000..7758b195
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-destroy-after-document-close.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] No more reports received after navigation to same document without endpoint header
+  assert_equals: expected 1 but got 0
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-named-endpoints.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-named-endpoints.https.sub-expected.txt
new file mode 100644
index 0000000..f008221
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-named-endpoints.https.sub-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Test that image does not load
+[PASS] csp violation report observed
+[PASS] document policy violation observed
+[FAIL] Reporting endpoints received reports.
+  assert_unreached: A report of csp-violation from https://web-platform.test:8444/reporting/document-reporting-named-endpoints.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-not-batch-different-document.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-not-batch-different-document.https-expected.txt
new file mode 100644
index 0000000..b5a44f7e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-not-batch-different-document.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Reports are not batched for same url in different document.
+  assert_equals: Number of reports expected 2 but got 0
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-override-endpoint.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-override-endpoint.https.sub-expected.txt
new file mode 100644
index 0000000..725f4c5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-override-endpoint.https.sub-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[PASS] document policy violation observed
+[FAIL] Only the second reporting endpoint received reports.
+  assert_unreached: A report of document-policy-violation from https://web-platform.test:8444/reporting/document-reporting-override-endpoint.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-path-absolute.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-path-absolute.https.sub-expected.txt
new file mode 100644
index 0000000..a878f4f7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/document-reporting-path-absolute.https.sub-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[PASS] report generated
+[FAIL] Reporting-Endpoints defined endpoint received reports.
+  assert_unreached: A report of deprecation from https://web-platform.test:8444/reporting/document-reporting-path-absolute.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/reporting-isolated-across-navigations.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/reporting-isolated-across-navigations.https.sub-expected.txt
new file mode 100644
index 0000000..5726f16
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/reporting-isolated-across-navigations.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Reports should be sent to the correct endpoints
+  assert_equals: First endpoint should receive two reports expected 2 but got 0
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/same-origin-cross-site-credentials.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/same-origin-cross-site-credentials.https.sub-expected.txt
new file mode 100644
index 0000000..ac88cef7c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/same-origin-cross-site-credentials.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Reporting endpoints received credentials.
+  assert_unreached: A report of csp-violation from https://web-platform.test:8444/reporting/resources/same-origin-report.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/same-origin-report-credentials.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/same-origin-report-credentials.https.sub-expected.txt
new file mode 100644
index 0000000..92c07a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/same-origin-report-credentials.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Reporting endpoints received credentials.
+  assert_unreached: A report of csp-violation from https://web-platform.test:8444/reporting/same-origin-report-credentials.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/same-origin-same-site-credentials.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/same-origin-same-site-credentials.https.sub-expected.txt
new file mode 100644
index 0000000..ac88cef7c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/reporting/same-origin-same-site-credentials.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Reporting endpoints received credentials.
+  assert_unreached: A report of csp-violation from https://web-platform.test:8444/reporting/resources/same-origin-report.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/resize-observer/svg-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/resize-observer/svg-expected.txt
new file mode 100644
index 0000000..70bc9e14
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/resize-observer/svg-expected.txt
@@ -0,0 +1,23 @@
+This is a testharness.js-based test.
+[PASS] ResizeObserver implemented
+[PASS] guard
+[PASS] test0: observe svg:circle
+[PASS] test1: observe svg:ellipse
+[PASS] test2: observe svg:foreignObject
+[PASS] test3: observe svg:image
+[PASS] test4: observe svg:line
+[PASS] test5: observe svg:path
+[PASS] test6: observe svg:polygon
+[PASS] test7: observe svg:polyline
+[PASS] test8: observe svg:rect
+[PASS] test9: observe svg:text
+[PASS] test10: observe svg:svg, top/left is 0 even with padding
+[PASS] test11: observe svg non-displayable element
+[PASS] test12: observe svg:rect content box
+[PASS] test13: observe svg:rect border box
+[PASS] test14: observe g:rect content and border box
+[FAIL] test15: observe svg:text content and border box
+  assert_equals: expected 360 but got 138.3125
+[PASS] test16: observe g:rect content, border and device-pixel-content boxes
+[PASS] test17: observe g:rect content, border and device-pixel-content boxes with zoom
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-document-hidden.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-document-hidden.https-expected.txt
new file mode 100644
index 0000000..b424bfd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-document-hidden.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] navigator.wakeLock.request('screen') fails when the document is hidden
+  assert_true: expected true got false
+[FAIL] Screen wake locks are released when the document the page is hidden
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-by-permissions-policy-attribute-redirect-on-load.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-by-permissions-policy-attribute-redirect-on-load.https-expected.txt
new file mode 100644
index 0000000..6798ae1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-by-permissions-policy-attribute-redirect-on-load.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Permissions-Policy allow="screen-wake-lock" allows same-origin relocation
+  assert_true: navigator.wakeLock.request("screen") expected true got false
+[PASS] Permissions-Policy allow="screen-wake-lock" disallows cross-origin relocation
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-by-permissions-policy-attribute.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-by-permissions-policy-attribute.https-expected.txt
new file mode 100644
index 0000000..dcfa5ee8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-by-permissions-policy-attribute.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] Permissions policy "screen-wake-lock" can be enabled in same-origin iframe using allow="screen-wake-lock" attribute
+  assert_true: navigator.wakeLock.request("screen") expected true got false
+[FAIL] Permissions policy "screen-wake-lock" can be enabled in cross-origin iframe using allow="screen-wake-lock" attribute
+  assert_true: navigator.wakeLock.request("screen") expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-by-permissions-policy.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-by-permissions-policy.https-expected.txt
new file mode 100644
index 0000000..2be95d7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-by-permissions-policy.https-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Permissions-Policy header "screen-wake-lock=*" allows the top-level document.
+[FAIL] Permissions-Policy header "screen-wake-lock=*" allows same-origin iframes.
+  assert_true: navigator.wakeLock.request("screen") expected true got false
+[FAIL] Permissions-Policy header "screen-wake-lock=*" allows cross-origin iframes.
+  assert_true: navigator.wakeLock.request("screen") expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-on-self-origin-by-permissions-policy.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-on-self-origin-by-permissions-policy.https-expected.txt
new file mode 100644
index 0000000..4fa645b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/screen-wake-lock/wakelock-enabled-on-self-origin-by-permissions-policy.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PASS] Permissions-Policy header "screen-wake-lock=self" allows the top-level document.
+[FAIL] Permissions-Policy header "screen-wake-lock=self" allows same-origin iframes.
+  assert_true: navigator.wakeLock.request("screen") expected true got false
+[PASS] Permissions-Policy header "screen-wake-lock=self" disallows cross-origin iframes.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/serial/requestPort/sandboxed_iframe.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/serial/requestPort/sandboxed_iframe.https.window-expected.txt
new file mode 100644
index 0000000..4e56b4d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/serial/requestPort/sandboxed_iframe.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] RequestPort from a sandboxed iframe is valid.
+  assert_equals: expected (object) object "[object Object]" but got (string) "FAIL: NotFoundError: Failed to execute 'requestPort' on 'Serial': No port selected by the user."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/service-workers/cache-storage/cache-add.https.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/service-workers/cache-storage/cache-add.https.any-expected.txt
new file mode 100644
index 0000000..bea1911
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/service-workers/cache-storage/cache-add.https.any-expected.txt
@@ -0,0 +1,25 @@
+This is a testharness.js-based test.
+[PASS] Cache.add called with no arguments
+[PASS] Cache.add called with relative URL specified as a string
+[PASS] Cache.add called with non-HTTP/HTTPS URL
+[PASS] Cache.add called with Request object
+[PASS] Cache.add called with POST request
+[PASS] Cache.add called twice with the same Request object
+[PASS] Cache.add with request with null body (not consumed)
+[PASS] Cache.add with 206 response
+[PASS] Cache.addAll with 206 response
+[PASS] Cache.addAll with opaque-filtered 206 response
+[PASS] Cache.add with request that results in a status of 404
+[PASS] Cache.add with request that results in a status of 500
+[PASS] Cache.addAll with no arguments
+[PASS] Cache.addAll with a mix of valid and undefined arguments
+[PASS] Cache.addAll with an empty array
+[PASS] Cache.addAll with string URL arguments
+[PASS] Cache.addAll with Request arguments
+[PASS] Cache.addAll with a mix of succeeding and failing requests
+[FAIL] Cache.addAll called with the same Request object specified twice
+  promise_rejects_dom: Cache.addAll should throw InvalidStateError if the same request is added twice. function "function() { throw e }" threw object "TypeError: Failed to execute 'addAll' on 'Cache': Request failed" that is not a DOMException InvalidStateError: property "code" is equal to undefined, expected 11
+[PASS] Cache.addAll should succeed when entries differ by vary header
+[PASS] Cache.addAll should reject when entries are duplicate by vary header
+[PASS] Cache.addAll should reject when one entry has a vary header matching another entry
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/service-workers/service-worker/fetch-event-referrer-policy.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/service-workers/service-worker/fetch-event-referrer-policy.https-expected.txt
new file mode 100644
index 0000000..990dc67
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/service-workers/service-worker/fetch-event-referrer-policy.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] Service Worker responds to fetch event with the referrer policy
+  promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+[PASS] Service Worker should respond to fetch with the default referrer policy
+[PASS] Service Worker should respond to fetch with the referrer URL when a member of RequestInit is present - Default Referrer
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/service-workers/service-worker/partitioned-matchAll.tentative.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/service-workers/service-worker/partitioned-matchAll.tentative.https-expected.txt
new file mode 100644
index 0000000..de0fac4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/service-workers/service-worker/partitioned-matchAll.tentative.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] ServiceWorker's matchAll() is partitioned
+  assert_equals: expected 1 but got 2
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/shape-detection/detection-ImageDataUint16StorageFormat.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/shape-detection/detection-ImageDataUint16StorageFormat.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/shape-detection/detection-ImageDataUint16StorageFormat.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-navigation-failed-zero-success-fraction.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-navigation-failed-zero-success-fraction.tentative-expected.txt
new file mode 100644
index 0000000..dde936b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-navigation-failed-zero-success-fraction.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] SXG error report must be downgraded when the cert URL is different from the reporting origin. And succeeded normal NEL report should not be sent  when success fraction is zero.
+  assert_true: SXG error reporting must be downgraded when the cert URL is different from the reporting origin expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-navigation-mi_error.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-navigation-mi_error.tentative-expected.txt
new file mode 100644
index 0000000..317fe57
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-navigation-mi_error.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] SXG reporting test of sxg.mi_error for navigation.
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-navigation-parse_error.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-navigation-parse_error.tentative-expected.txt
new file mode 100644
index 0000000..cae1840c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-navigation-parse_error.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] SXG reporting test of sxg.parse_error for navigation.
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-prefetch-failed-zero-success-feaction.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-prefetch-failed-zero-success-feaction.tentative-expected.txt
new file mode 100644
index 0000000..dde936b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/signed-exchange/reporting/sxg-reporting-prefetch-failed-zero-success-feaction.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] SXG error report must be downgraded when the cert URL is different from the reporting origin. And succeeded normal NEL report should not be sent  when success fraction is zero.
+  assert_true: SXG error reporting must be downgraded when the cert URL is different from the reporting origin expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/prefetch.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/prefetch.https-expected.txt
new file mode 100644
index 0000000..3a0964a6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/prefetch.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Prerender navigation requests should use prefetched results
+  assert_equals: expected "activated" but got "discarded"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful-expected.txt
new file mode 100644
index 0000000..fe555d0f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Responses with code 203 should be activated
+  assert_equals: expected "activated" but got "discarded"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=200-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=200-expected.txt
new file mode 100644
index 0000000..66e3320
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=200-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Responses with code 200 should be activated
+  assert_equals: expected "activated" but got "discarded"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=201-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=201-expected.txt
new file mode 100644
index 0000000..1759a86
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=201-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Responses with code 201 should be activated
+  assert_equals: expected "activated" but got "discarded"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=203-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=203-expected.txt
new file mode 100644
index 0000000..fe555d0f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=203-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Responses with code 203 should be activated
+  assert_equals: expected "activated" but got "discarded"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=232-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=232-expected.txt
new file mode 100644
index 0000000..3884cfe
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speculation-rules/prerender/response-code-successful_code=232-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Responses with code 232 should be activated
+  assert_equals: expected "activated" but got "discarded"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesis-speak-events-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesis-speak-events-expected.txt
new file mode 100644
index 0000000..eee0abf
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesis-speak-events-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] speechSynthesis.speak() fires start and end events with empty utterance
+  assert_equals: Expected start event, but got error event instead expected "start" but got "error"
+[FAIL] speechSynthesis.speak() fires start and end events
+  assert_equals: Expected start event, but got error event instead expected "start" but got "error"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesis-speak-twice-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesis-speak-twice-expected.txt
new file mode 100644
index 0000000..6820b593
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesis-speak-twice-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Using the same SpeechSynthesisUtterance twice for speechSynthesis.speak()
+  assert_unreached: error event Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesisEvent-properties-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesisEvent-properties-expected.txt
new file mode 100644
index 0000000..eb26431
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/speech-api/SpeechSynthesisEvent-properties-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Properties of SpeechSynthesisEvent
+  assert_equals: Expected start event, but got error event instead expected "start" but got "error"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/hasStorageAccess-ABA.tentative.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/hasStorageAccess-ABA.tentative.sub.https.window-expected.txt
new file mode 100644
index 0000000..6cee33c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/hasStorageAccess-ABA.tentative.sub.https.window-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PASS] [ABA] document.hasStorageAccess() should exist on the document interface
+[FAIL] [ABA] document.hasStorageAccess() should not be allowed by default unless in top-level frame or same-origin iframe.
+  assert_false: Access should not be granted in secure same-origin iframe that is in a third-party context by default. expected false got true
+[PASS] [ABA] document.hasStorageAccess() should reject in a document that isn't fully active.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/hasStorageAccess.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/hasStorageAccess.sub.https.window-expected.txt
new file mode 100644
index 0000000..8b4ac674
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/hasStorageAccess.sub.https.window-expected.txt
@@ -0,0 +1,19 @@
+This is a testharness.js-based test.
+[PASS] [top-level-context] document.hasStorageAccess() should exist on the document interface
+[PASS] [top-level-context] document.hasStorageAccess() should not be allowed by default unless in top-level frame or same-origin iframe.
+[PASS] [top-level-context] document.hasStorageAccess() should reject in a document that isn't fully active.
+[PASS] [same-origin-frame] document.hasStorageAccess() should exist on the document interface
+[PASS] [same-origin-frame] document.hasStorageAccess() should not be allowed by default unless in top-level frame or same-origin iframe.
+[PASS] [same-origin-frame] document.hasStorageAccess() should reject in a document that isn't fully active.
+[PASS] [cross-site-frame] document.hasStorageAccess() should exist on the document interface
+[FAIL] [cross-site-frame] document.hasStorageAccess() should not be allowed by default unless in top-level frame or same-origin iframe.
+  assert_false: Access should not be granted in secure cross-origin iframes. expected false got true
+[PASS] [cross-site-frame] document.hasStorageAccess() should reject in a document that isn't fully active.
+[PASS] [nested-same-origin-frame] document.hasStorageAccess() should exist on the document interface
+[PASS] [nested-same-origin-frame] document.hasStorageAccess() should not be allowed by default unless in top-level frame or same-origin iframe.
+[PASS] [nested-same-origin-frame] document.hasStorageAccess() should reject in a document that isn't fully active.
+[PASS] [nested-cross-site-frame] document.hasStorageAccess() should exist on the document interface
+[FAIL] [nested-cross-site-frame] document.hasStorageAccess() should not be allowed by default unless in top-level frame or same-origin iframe.
+  assert_false: Access should not be granted in secure cross-origin iframes. expected false got true
+[PASS] [nested-cross-site-frame] document.hasStorageAccess() should reject in a document that isn't fully active.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-ABA.tentative.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-ABA.tentative.sub.https.window-expected.txt
new file mode 100644
index 0000000..de8fb22
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-ABA.tentative.sub.https.window-expected.txt
@@ -0,0 +1,11 @@
+This is a testharness.js-based test.
+[PASS] [ABA] document.requestStorageAccess() should exist on the document interface
+[FAIL] [ABA] document.requestStorageAccess() should resolve in top-level frame or same-site iframe, otherwise reject with a NotAllowedError with no user gesture.
+  assert_unreached: document.requestStorageAccess() call should resolve in top-level frame or same-site iframe. Reached unreachable code
+[FAIL] [ABA] document.requestStorageAccess() should be resolved with no user gesture when a permission grant exists, and should allow cookie access
+  promise_test: Unhandled rejection with value: object "NotAllowedError: requestStorageAccess not allowed"
+[FAIL] [ABA] document.requestStorageAccess() should resolve without permission grant or user gesture
+  promise_test: Unhandled rejection with value: object "NotAllowedError: requestStorageAccess not allowed"
+[FAIL] [ABA] document.requestStorageAccess() should resolve with denied permission
+  promise_test: Unhandled rejection with value: object "NotAllowedError: requestStorageAccess not allowed"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window-expected.txt
new file mode 100644
index 0000000..27d3331f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+[FAIL] Self-initiated reloads preserve storage access
+  assert_false: frame initially does not have storage access. expected false got true
+[FAIL] Self-initiated same-origin navigations preserve storage access
+  assert_false: frame initially does not have storage access. expected false got true
+[FAIL] Non-self-initiated same-origin navigations do not preserve storage access
+  assert_false: frame initially does not have storage access. expected false got true
+[FAIL] Self-initiated cross-origin navigations do not preserve storage access
+  assert_false: frame initially does not have storage access. expected false got true
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window-expected.txt
new file mode 100644
index 0000000..9a9eabd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-cross-site-sibling-iframes.sub.https.window-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] Grants have per-frame scope
+  assert_false: frame1 should not have storage access initially. expected false got true
+[FAIL] Cross-site sibling iframes should not be able to take advantage of the existing permission grant requested by others.
+  assert_true: crossOriginFrame should be able to get storage access without a gesture. expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-dedicated-worker.tentative.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-dedicated-worker.tentative.sub.https.window-expected.txt
new file mode 100644
index 0000000..8bd56bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-dedicated-worker.tentative.sub.https.window-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] Workers inherit storage access
+  assert_true: requestStorageAccess resolves without requiring a gesture. expected true got false
+[FAIL] Workers don't observe parent's storage access
+  assert_equals: Worker's first fetch is uncredentialed. expected "" but got "cookie=unpartitioned"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-nested-same-origin-iframe.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-nested-same-origin-iframe.sub.https.window-expected.txt
new file mode 100644
index 0000000..f2dc7b6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-nested-same-origin-iframe.sub.https.window-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+[PASS] [nested-same-origin-frame] document.requestStorageAccess() should exist on the document interface
+[FAIL] [nested-same-origin-frame] document.requestStorageAccess() should resolve in top-level frame or same-site iframe, otherwise reject with a NotAllowedError with no user gesture.
+  assert_unreached: document.requestStorageAccess() call should resolve in top-level frame or same-site iframe. Reached unreachable code
+[PASS] [nested-same-origin-frame] document.requestStorageAccess() should be resolved with no user gesture when a permission grant exists, and should allow cookie access
+[FAIL] [nested-same-origin-frame] document.requestStorageAccess() should resolve without permission grant or user gesture
+  promise_test: Unhandled rejection with value: object "NotAllowedError: requestStorageAccess not allowed"
+[FAIL] [nested-same-origin-frame] document.requestStorageAccess() should resolve with denied permission
+  promise_test: Unhandled rejection with value: object "NotAllowedError: requestStorageAccess not allowed"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-same-site-iframe.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-same-site-iframe.sub.https.window-expected.txt
new file mode 100644
index 0000000..820f470f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/requestStorageAccess-same-site-iframe.sub.https.window-expected.txt
@@ -0,0 +1,11 @@
+This is a testharness.js-based test.
+[PASS] [same-site-frame] document.requestStorageAccess() should exist on the document interface
+[FAIL] [same-site-frame] document.requestStorageAccess() should resolve in top-level frame or same-site iframe, otherwise reject with a NotAllowedError with no user gesture.
+  assert_unreached: document.requestStorageAccess() call should resolve in top-level frame or same-site iframe. Reached unreachable code
+[FAIL] [same-site-frame] document.requestStorageAccess() should be resolved with no user gesture when a permission grant exists, and should allow cookie access
+  promise_test: Unhandled rejection with value: object "NotAllowedError: requestStorageAccess not allowed"
+[FAIL] [same-site-frame] document.requestStorageAccess() should resolve without permission grant or user gesture
+  promise_test: Unhandled rejection with value: object "NotAllowedError: requestStorageAccess not allowed"
+[FAIL] [same-site-frame] document.requestStorageAccess() should resolve with denied permission
+  promise_test: Unhandled rejection with value: object "NotAllowedError: requestStorageAccess not allowed"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.caches.tentative.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.caches.tentative.sub.https.window-expected.txt
new file mode 100644
index 0000000..69baced
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.caches.tentative.sub.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verify StorageAccessAPIBeyondCookies for Cache Storage
+  assert_equals: Storage Access API should be accessible and return first-party data expected (string) "HasAccess for caches" but got (object) object "[object Object]"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.getDirectory.tentative.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.getDirectory.tentative.sub.https.window-expected.txt
new file mode 100644
index 0000000..f5c58e9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.getDirectory.tentative.sub.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verify StorageAccessAPIBeyondCookies for Origin Private File System
+  assert_equals: Storage Access API should be accessible and return first-party data expected (string) "HasAccess for getDirectory" but got (object) object "[object Object]"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.indexedDB.tentative.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.indexedDB.tentative.sub.https.window-expected.txt
new file mode 100644
index 0000000..a7d0c8e3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.indexedDB.tentative.sub.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verify StorageAccessAPIBeyondCookies for IndexedDB
+  assert_equals: Storage Access API should be accessible and return first-party data expected (string) "HasAccess for indexedDB" but got (object) object "[object Object]"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.localStorage.tentative.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.localStorage.tentative.sub.https.window-expected.txt
new file mode 100644
index 0000000..f53e2c8c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.localStorage.tentative.sub.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verify StorageAccessAPIBeyondCookies for Local Storage
+  assert_equals: Storage Access API should be accessible and return first-party data expected (string) "HasAccess for localStorage" but got (object) object "[object Object]"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.locks.tentative.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.locks.tentative.sub.https.window-expected.txt
new file mode 100644
index 0000000..a7bd3db
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.locks.tentative.sub.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verify StorageAccessAPIBeyondCookies for Web Locks
+  assert_equals: Storage Access API should be accessible and return first-party data expected (string) "HasAccess for locks" but got (object) object "[object Object]"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.sessionStorage.tentative.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.sessionStorage.tentative.sub.https.window-expected.txt
new file mode 100644
index 0000000..4d5e171
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storage-access-beyond-cookies.sessionStorage.tentative.sub.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verify StorageAccessAPIBeyondCookies for Session Storage
+  assert_equals: Storage Access API should be accessible and return first-party data expected (string) "HasAccess for sessionStorage" but got (object) object "[object Object]"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storageAccess.testdriver.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storageAccess.testdriver.sub-expected.txt
new file mode 100644
index 0000000..bb9a685
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/storage-access-api/storageAccess.testdriver.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] TestDriver - Set Storage Access Command Tests
+  assert_false: Cross-site iframe should not be allowed to write cookies via document.cookie. expected false got true
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/svg/interact/scripted/svg-pointer-events-bbox-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/svg/interact/scripted/svg-pointer-events-bbox-expected.txt
new file mode 100644
index 0000000..c3772ea
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/svg/interact/scripted/svg-pointer-events-bbox-expected.txt
@@ -0,0 +1,38 @@
+This is a testharness.js-based test.
+[PASS] circle1 contains point at (36, 60)
+[PASS] circle1 contains point at (42, 67)
+[PASS] circle1 does not contain point at (50, 50)
+[PASS] circle1 does not contain point at (50, 55)
+[PASS] group1 contains point at (100, 100)
+[PASS] group1 contains point at (137, 84)
+[PASS] group1 contains point at (51, 156)
+[PASS] group1 contains point at (70, 120)
+[PASS] circle2 contains point at (400, 150)
+[PASS] circle2 contains point at (432, 182)
+[PASS] circle2 contains point at (361, 122)
+[PASS] bbox of circle2 contains point at (438, 103)
+[PASS] bbox of circle2 contains point at (450, 200)
+[PASS] text1 contains point at (134, 16)
+[FAIL] tspan1 contains point at (579, 46)
+  assert_true: expected true got false
+[PASS] text1 does not contain point at (395, 73)
+[PASS] text1 does not contain point at (74, 5)
+[FAIL] bbox of text1 contains point at (435, 32)
+  assert_true: expected true got false
+[PASS] bbox of text1 contains point at (115, 46)
+[PASS] text2 contains point at (178, 146)
+[FAIL] tspan2 contains point at (568, 283)
+  assert_true: expected true got false
+[PASS] text2 does not contain point at (319, 161)
+[PASS] text2 does not contain point at (179, 131)
+[PASS] bbox of text2 contains point at (295, 214)
+[FAIL] bbox of text2 contains point at (444, 222)
+  assert_true: expected true got false
+[PASS] text3 contains point at (198, 291)
+[FAIL] text3 contains point at (286, 301)
+  assert_true: expected true got false
+[PASS] text3 does not contain point at (302, 337)
+[PASS] text3 does not contain point at (348, 335)
+[PASS] image1 contains point at (19, 215)
+[PASS] image1 contains point at (45, 225)
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/top-level-storage-access-api/tentative/requestStorageAccessFor.sub.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/top-level-storage-access-api/tentative/requestStorageAccessFor.sub.https.window-expected.txt
new file mode 100644
index 0000000..1ac1042
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/top-level-storage-access-api/tentative/requestStorageAccessFor.sub.https.window-expected.txt
@@ -0,0 +1,19 @@
+This is a testharness.js-based test.
+[PASS] [top-level-context] document.requestStorageAccessFor() should be supported on the document interface
+[PASS] [top-level-context] document.requestStorageAccessFor() should be rejected when called with no argument
+[PASS] [top-level-context] document.requestStorageAccessFor() should be rejected by default with no user gesture
+[PASS] [non-fully-active] document.requestStorageAccessFor() should not resolve when run in a detached frame
+[PASS] [non-fully-active] document.requestStorageAccessFor() should not resolve when run in a detached DOMParser document
+[PASS] [top-level-context] document.requestStorageAccessFor() should be resolved without a user gesture with an existing permission
+[FAIL] [top-level-context] document.requestStorageAccess() should be resolved without a user gesture after a successful requestStorageAccessFor() call
+  assert_true: expected true got false
+[PASS] [top-level-context] document.requestStorageAccessFor() should be resolved when called properly with a user gesture and the same origin
+[PASS] [top-level-context] document.requestStorageAccessFor() should be rejected when called with an invalid origin
+[PASS] [top-level-context] document.requestStorageAccessFor() should be rejected when called with an opaque origin
+[PASS] [top-level-context] Top-level storage access only allows cross-site subresource requests to access cookie when using CORS mode.
+[PASS] [same-origin-iframe] document.requestStorageAccessFor() should be supported on the document interface
+[PASS] [same-origin-iframe] document.requestStorageAccessFor() should be rejected when called with no argument
+[PASS] [same-origin-iframe] document.requestStorageAccessFor() should be rejected when called in an iframe
+[FAIL] [same-origin-iframe] Existing top-level storage access permission should not allow cookie access for the cross-site subresource requests made in a non-top-level context.
+  assert_false: expected false got true
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/touch-events/idlharness.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/touch-events/idlharness.window-expected.txt
new file mode 100644
index 0000000..d0ce17f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/touch-events/idlharness.window-expected.txt
@@ -0,0 +1,166 @@
+This is a testharness.js-based test.
+Found 126 tests; 89 PASS, 37 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[PASS] idl_test setup
+[PASS] idl_test validation
+[PASS] Partial interface mixin GlobalEventHandlers: original interface mixin defined
+[PASS] Partial interface mixin GlobalEventHandlers: member names are unique
+[PASS] Partial interface UIEvent: member names are unique
+[PASS] Partial interface UIEvent[2]: member names are unique
+[PASS] Partial dictionary UIEventInit: member names are unique
+[PASS] Partial interface Document: member names are unique
+[PASS] Partial interface Document[2]: member names are unique
+[PASS] Partial interface Window: member names are unique
+[PASS] Document includes GlobalEventHandlers: member names are unique
+[PASS] HTMLElement includes GlobalEventHandlers: member names are unique
+[PASS] HTMLElement includes ElementContentEditable: member names are unique
+[PASS] HTMLElement includes HTMLOrSVGElement: member names are unique
+[PASS] Window includes GlobalEventHandlers: member names are unique
+[PASS] Window includes WindowEventHandlers: member names are unique
+[PASS] Window includes WindowOrWorkerGlobalScope: member names are unique
+[PASS] Window includes AnimationFrameProvider: member names are unique
+[PASS] Window includes WindowSessionStorage: member names are unique
+[PASS] Window includes WindowLocalStorage: member names are unique
+[PASS] Document includes NonElementParentNode: member names are unique
+[PASS] Document includes ParentNode: member names are unique
+[PASS] Element includes ParentNode: member names are unique
+[PASS] Element includes NonDocumentTypeChildNode: member names are unique
+[PASS] Element includes ChildNode: member names are unique
+[PASS] Element includes Slottable: member names are unique
+[PASS] Document includes XPathEvaluatorBase: member names are unique
+[PASS] Touch interface: existence and properties of interface object
+[PASS] Touch interface object length
+[PASS] Touch interface object name
+[PASS] Touch interface: existence and properties of interface prototype object
+[PASS] Touch interface: existence and properties of interface prototype object's "constructor" property
+[PASS] Touch interface: existence and properties of interface prototype object's @@unscopables property
+[PASS] Touch interface: attribute identifier
+[PASS] Touch interface: attribute target
+[PASS] Touch interface: attribute screenX
+[PASS] Touch interface: attribute screenY
+[PASS] Touch interface: attribute clientX
+[PASS] Touch interface: attribute clientY
+[PASS] Touch interface: attribute pageX
+[PASS] Touch interface: attribute pageY
+[PASS] Touch interface: attribute radiusX
+[PASS] Touch interface: attribute radiusY
+[PASS] Touch interface: attribute rotationAngle
+[PASS] Touch interface: attribute force
+[FAIL] Touch interface: attribute altitudeAngle
+  assert_true: The prototype object must have a property "altitudeAngle" expected true got false
+[FAIL] Touch interface: attribute azimuthAngle
+  assert_true: The prototype object must have a property "azimuthAngle" expected true got false
+[FAIL] Touch interface: attribute touchType
+  assert_true: The prototype object must have a property "touchType" expected true got false
+[PASS] Touch must be primary interface of new Touch({identifier: 1, target: document})
+[PASS] Stringification of new Touch({identifier: 1, target: document})
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "identifier" with the proper type
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "target" with the proper type
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "screenX" with the proper type
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "screenY" with the proper type
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "clientX" with the proper type
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "clientY" with the proper type
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "pageX" with the proper type
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "pageY" with the proper type
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "radiusX" with the proper type
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "radiusY" with the proper type
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "rotationAngle" with the proper type
+[PASS] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "force" with the proper type
+[FAIL] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "altitudeAngle" with the proper type
+  assert_inherits: property "altitudeAngle" not found in prototype chain
+[FAIL] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "azimuthAngle" with the proper type
+  assert_inherits: property "azimuthAngle" not found in prototype chain
+[FAIL] Touch interface: new Touch({identifier: 1, target: document}) must inherit property "touchType" with the proper type
+  assert_inherits: property "touchType" not found in prototype chain
+[PASS] TouchList interface: existence and properties of interface object
+[PASS] TouchList interface object length
+[PASS] TouchList interface object name
+[PASS] TouchList interface: existence and properties of interface prototype object
+[PASS] TouchList interface: existence and properties of interface prototype object's "constructor" property
+[PASS] TouchList interface: existence and properties of interface prototype object's @@unscopables property
+[PASS] TouchList interface: attribute length
+[PASS] TouchList interface: operation item(unsigned long)
+[PASS] TouchEvent interface: existence and properties of interface object
+[PASS] TouchEvent interface object length
+[PASS] TouchEvent interface object name
+[PASS] TouchEvent interface: existence and properties of interface prototype object
+[PASS] TouchEvent interface: existence and properties of interface prototype object's "constructor" property
+[PASS] TouchEvent interface: existence and properties of interface prototype object's @@unscopables property
+[PASS] TouchEvent interface: attribute touches
+[PASS] TouchEvent interface: attribute targetTouches
+[PASS] TouchEvent interface: attribute changedTouches
+[PASS] TouchEvent interface: attribute altKey
+[PASS] TouchEvent interface: attribute metaKey
+[PASS] TouchEvent interface: attribute ctrlKey
+[PASS] TouchEvent interface: attribute shiftKey
+[FAIL] TouchEvent interface: operation getModifierState(DOMString)
+  assert_own_property: interface prototype object missing non-static operation expected property "getModifierState" missing
+[PASS] TouchEvent must be primary interface of new TouchEvent("name")
+[PASS] Stringification of new TouchEvent("name")
+[PASS] TouchEvent interface: new TouchEvent("name") must inherit property "touches" with the proper type
+[PASS] TouchEvent interface: new TouchEvent("name") must inherit property "targetTouches" with the proper type
+[PASS] TouchEvent interface: new TouchEvent("name") must inherit property "changedTouches" with the proper type
+[PASS] TouchEvent interface: new TouchEvent("name") must inherit property "altKey" with the proper type
+[PASS] TouchEvent interface: new TouchEvent("name") must inherit property "metaKey" with the proper type
+[PASS] TouchEvent interface: new TouchEvent("name") must inherit property "ctrlKey" with the proper type
+[PASS] TouchEvent interface: new TouchEvent("name") must inherit property "shiftKey" with the proper type
+[FAIL] TouchEvent interface: new TouchEvent("name") must inherit property "getModifierState(DOMString)" with the proper type
+  assert_inherits: property "getModifierState" not found in prototype chain
+[FAIL] TouchEvent interface: calling getModifierState(DOMString) on new TouchEvent("name") with too few arguments must throw TypeError
+  assert_inherits: property "getModifierState" not found in prototype chain
+[FAIL] HTMLElement interface: attribute ontouchstart
+  assert_true: The prototype object must have a property "ontouchstart" expected true got false
+[FAIL] HTMLElement interface: attribute ontouchend
+  assert_true: The prototype object must have a property "ontouchend" expected true got false
+[FAIL] HTMLElement interface: attribute ontouchmove
+  assert_true: The prototype object must have a property "ontouchmove" expected true got false
+[FAIL] HTMLElement interface: attribute ontouchcancel
+  assert_true: The prototype object must have a property "ontouchcancel" expected true got false
+[FAIL] Window interface: attribute ontouchstart
+  assert_own_property: The global object must have a property "ontouchstart" expected property "ontouchstart" missing
+[FAIL] Window interface: attribute ontouchend
+  assert_own_property: The global object must have a property "ontouchend" expected property "ontouchend" missing
+[FAIL] Window interface: attribute ontouchmove
+  assert_own_property: The global object must have a property "ontouchmove" expected property "ontouchmove" missing
+[FAIL] Window interface: attribute ontouchcancel
+  assert_own_property: The global object must have a property "ontouchcancel" expected property "ontouchcancel" missing
+[FAIL] GlobalEventHandlers interface: window must inherit property "ontouchstart" with the proper type
+  assert_inherits: property "ontouchstart" not found in prototype chain
+[FAIL] GlobalEventHandlers interface: window must inherit property "ontouchend" with the proper type
+  assert_inherits: property "ontouchend" not found in prototype chain
+[FAIL] GlobalEventHandlers interface: window must inherit property "ontouchmove" with the proper type
+  assert_inherits: property "ontouchmove" not found in prototype chain
+[FAIL] GlobalEventHandlers interface: window must inherit property "ontouchcancel" with the proper type
+  assert_inherits: property "ontouchcancel" not found in prototype chain
+[FAIL] GlobalEventHandlers interface: document must inherit property "ontouchstart" with the proper type
+  assert_inherits: property "ontouchstart" not found in prototype chain
+[FAIL] GlobalEventHandlers interface: document must inherit property "ontouchend" with the proper type
+  assert_inherits: property "ontouchend" not found in prototype chain
+[FAIL] GlobalEventHandlers interface: document must inherit property "ontouchmove" with the proper type
+  assert_inherits: property "ontouchmove" not found in prototype chain
+[FAIL] GlobalEventHandlers interface: document must inherit property "ontouchcancel" with the proper type
+  assert_inherits: property "ontouchcancel" not found in prototype chain
+[FAIL] GlobalEventHandlers interface: document.body must inherit property "ontouchstart" with the proper type
+  assert_inherits: property "ontouchstart" not found in prototype chain
+[FAIL] GlobalEventHandlers interface: document.body must inherit property "ontouchend" with the proper type
+  assert_inherits: property "ontouchend" not found in prototype chain
+[FAIL] GlobalEventHandlers interface: document.body must inherit property "ontouchmove" with the proper type
+  assert_inherits: property "ontouchmove" not found in prototype chain
+[FAIL] GlobalEventHandlers interface: document.body must inherit property "ontouchcancel" with the proper type
+  assert_inherits: property "ontouchcancel" not found in prototype chain
+[FAIL] Document interface: attribute ontouchstart
+  assert_true: The prototype object must have a property "ontouchstart" expected true got false
+[FAIL] Document interface: attribute ontouchend
+  assert_true: The prototype object must have a property "ontouchend" expected true got false
+[FAIL] Document interface: attribute ontouchmove
+  assert_true: The prototype object must have a property "ontouchmove" expected true got false
+[FAIL] Document interface: attribute ontouchcancel
+  assert_true: The prototype object must have a property "ontouchcancel" expected true got false
+[FAIL] Document interface: document must inherit property "ontouchstart" with the proper type
+  assert_inherits: property "ontouchstart" not found in prototype chain
+[FAIL] Document interface: document must inherit property "ontouchend" with the proper type
+  assert_inherits: property "ontouchend" not found in prototype chain
+[FAIL] Document interface: document must inherit property "ontouchmove" with the proper type
+  assert_inherits: property "ontouchmove" not found in prototype chain
+[FAIL] Document interface: document must inherit property "ontouchcancel" with the proper type
+  assert_inherits: property "ontouchcancel" not found in prototype chain
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/touch-events/touch-globaleventhandler-interface-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/touch-events/touch-globaleventhandler-interface-expected.txt
new file mode 100644
index 0000000..440f89ff
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/touch-events/touch-globaleventhandler-interface-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Touch events in GlobalEventHandlers
+  'expose legacy touch event APIs'
+[PRECONDITION_FAILED] Touch events are GlobalEventHandlers' own property
+  'expose legacy touch event APIs'
+[PASS] Touch events not in Element.prototype
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/visual-viewport/resize-event-order-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/visual-viewport/resize-event-order-expected.txt
new file mode 100644
index 0000000..ba48009
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/visual-viewport/resize-event-order-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Popup: DOMWindow resize fired before VisualViewport.
+  assert_equals: expected "window-attribute,window-addEventListener,visualViewport-attribute,visualViewport-addEventListener" but got ""
+[PASS] iframe: DOMWindow resize fired before VisualViewport.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/web-animations/timing-model/timelines/timelines-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/web-animations/timing-model/timelines/timelines-expected.txt
new file mode 100644
index 0000000..cb761f0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/web-animations/timing-model/timelines/timelines-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[PASS] Timeline time increases once per animation frame
+[FAIL] Timeline time increases once per animation frame in an iframe
+  assert_greater_than: Timeline time within an iframe increases between animation frames expected a number greater than 0 but got 0
+[PASS] Timeline time should be the same for all RAF callbacks in an animation frame
+[PASS] Performs a microtask checkpoint after updating timelines
+[PASS] Runs finished promise before animation events
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/web-bundle/subresource-loading/csp-blocked.https.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/web-bundle/subresource-loading/csp-blocked.https.tentative-expected.txt
new file mode 100644
index 0000000..2056e3b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/web-bundle/subresource-loading/csp-blocked.https.tentative-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PASS] URL matching of CSP should be done based on the subresource URL, not on the bundle URL, when the subresource URL is HTTPS URL.
+[PASS] URL matching of script-src CSP should be done based on the bundle URL when the subresource URL is uuid-in-package: URL.
+[FAIL] Check the CSP violation reports.
+  assert_equals: Report count. expected 2 but got 0
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/web-share/disabled-by-permissions-policy-cross-origin.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/web-share/disabled-by-permissions-policy-cross-origin.https.sub-expected.txt
new file mode 100644
index 0000000..548e82f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/web-share/disabled-by-permissions-policy-cross-origin.https.sub-expected.txt
@@ -0,0 +1,11 @@
+This is a testharness.js-based test.
+[FAIL] share() is disabled by default 'self' by permissions policy for cross-origin iframes
+  assert_equals: expected "NotAllowedError" but got "Error"
+[FAIL] share() is disabled explicitly by permissions policy for cross-origin iframe
+  assert_equals: expected "NotAllowedError" but got "Error"
+[FAIL] share() not allowed, as only allowed to share with self
+  assert_equals: expected "NotAllowedError" but got "Error"
+[PASS] canShare() not allowed to share by default permissions policy cross-origin
+[PASS] canShare() is allowed by permissions policy to share cross-origin on a particular origin
+[PASS] canShare() with self
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-state-change-after-close.http.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-state-change-after-close.http.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-state-change-after-close.http.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/suspend-with-navigation-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/suspend-with-navigation-expected.txt
new file mode 100644
index 0000000..6d48115
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/suspend-with-navigation-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] suspend() with navigation
+  Could have been BFCached but actually wasn't
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-default-value.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-default-value.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-default-value.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webauthn/public-key-credential-to-json.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webauthn/public-key-credential-to-json.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webauthn/public-key-credential-to-json.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any-expected.txt
new file mode 100644
index 0000000..dc00111c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any-expected.txt
@@ -0,0 +1,38 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Test isConfigSupported()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test isConfigSupported() with 1080p crop
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test that isConfigSupported() returns a parsed configuration
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test invalid configs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test configure()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a key frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a non key frame first fails
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Verify reset() suppresses outputs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test unconfigured VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test closed VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode empty frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Close while decoding corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding after flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding a with negative timestamp
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test reset during flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test low-latency decoding
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] VideoDecoder decodeQueueSize test
+  hev1.1.6.L60.90 unsupported
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker-expected.txt
new file mode 100644
index 0000000..dc00111c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker-expected.txt
@@ -0,0 +1,38 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Test isConfigSupported()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test isConfigSupported() with 1080p crop
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test that isConfigSupported() returns a parsed configuration
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test invalid configs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test configure()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a key frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a non key frame first fails
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Verify reset() suppresses outputs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test unconfigured VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test closed VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode empty frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Close while decoding corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding after flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding a with negative timestamp
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test reset during flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test low-latency decoding
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] VideoDecoder decodeQueueSize test
+  hev1.1.6.L60.90 unsupported
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_annexb-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_annexb-expected.txt
new file mode 100644
index 0000000..dc00111c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_annexb-expected.txt
@@ -0,0 +1,38 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Test isConfigSupported()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test isConfigSupported() with 1080p crop
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test that isConfigSupported() returns a parsed configuration
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test invalid configs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test configure()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a key frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a non key frame first fails
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Verify reset() suppresses outputs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test unconfigured VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test closed VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode empty frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Close while decoding corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding after flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding a with negative timestamp
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test reset during flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test low-latency decoding
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] VideoDecoder decodeQueueSize test
+  hev1.1.6.L60.90 unsupported
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_hevc-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_hevc-expected.txt
new file mode 100644
index 0000000..dc00111c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_hevc-expected.txt
@@ -0,0 +1,38 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Test isConfigSupported()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test isConfigSupported() with 1080p crop
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test that isConfigSupported() returns a parsed configuration
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test invalid configs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test configure()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a key frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a non key frame first fails
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Verify reset() suppresses outputs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test unconfigured VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test closed VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode empty frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Close while decoding corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding after flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding a with negative timestamp
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test reset during flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test low-latency decoding
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] VideoDecoder decodeQueueSize test
+  hev1.1.6.L60.90 unsupported
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_annexb-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_annexb-expected.txt
new file mode 100644
index 0000000..dc00111c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_annexb-expected.txt
@@ -0,0 +1,38 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Test isConfigSupported()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test isConfigSupported() with 1080p crop
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test that isConfigSupported() returns a parsed configuration
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test invalid configs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test configure()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a key frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a non key frame first fails
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Verify reset() suppresses outputs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test unconfigured VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test closed VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode empty frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Close while decoding corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding after flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding a with negative timestamp
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test reset during flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test low-latency decoding
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] VideoDecoder decodeQueueSize test
+  hev1.1.6.L60.90 unsupported
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_hevc-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_hevc-expected.txt
new file mode 100644
index 0000000..dc00111c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_hevc-expected.txt
@@ -0,0 +1,38 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Test isConfigSupported()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test isConfigSupported() with 1080p crop
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test that isConfigSupported() returns a parsed configuration
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test invalid configs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test configure()
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a key frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode a non key frame first fails
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Verify reset() suppresses outputs
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test unconfigured VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test closed VideoDecoder operations
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode empty frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Decode corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Close while decoding corrupt frame
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding after flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test decoding a with negative timestamp
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test reset during flush
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] Test low-latency decoding
+  hev1.1.6.L60.90 unsupported
+[PRECONDITION_FAILED] VideoDecoder decodeQueueSize test
+  hev1.1.6.L60.90 unsupported
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc-extensions/transfer-datachannel-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc-extensions/transfer-datachannel-expected.txt
new file mode 100644
index 0000000..c687cdb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc-extensions/transfer-datachannel-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Failed to execute 'postMessage' on 'Worker': Value at index 0 does not have a transferable type.
+[TIMEOUT] offerer data channel in workers
+  Test timed out
+[NOTRUN] answerer data channel in workers
+[NOTRUN] data channel close event in worker
+[NOTRUN] Failing to transfer a data channel
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc-extensions/transfer-datachannel-service-worker.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc-extensions/transfer-datachannel-service-worker.https-expected.txt
new file mode 100644
index 0000000..27a0926
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc-extensions/transfer-datachannel-service-worker.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Failed to execute 'postMessage' on 'ServiceWorker': Value at index 0 does not have a transferable type.
+[TIMEOUT] offerer data channel in service worker
+  Test timed out
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/RTCPeerConnection-operations.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/RTCPeerConnection-operations.https-expected.txt
new file mode 100644
index 0000000..62572449
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/RTCPeerConnection-operations.https-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Failed to execute 'setLocalDescription' on 'RTCPeerConnection': Failed to parse SessionDescription.  Expect line: v=
+[PASS] promiseState helper works
+[PASS] promiseStateFinal helper works
+[FAIL] createOffer must detect InvalidStateError synchronously when chain is empty (prerequisite)
+  assert_equals: expected "InvalidStateError" but got "Error"
+[FAIL] createAnswer must detect InvalidStateError synchronously when chain is empty (prerequisite)
+  assert_equals: promise rejected on same task expected "rejected" but got "pending"
+[FAIL] SLD(rollback) must detect InvalidStateError synchronously when chain is empty
+  assert_equals: promise rejected on same task expected "rejected" but got "pending"
+[FAIL] addIceCandidate must detect InvalidStateError synchronously when chain is empty
+  assert_equals: expected "InvalidStateError" but got "Error"
+[PASS] replaceTrack must detect InvalidStateError synchronously when chain is empty and transceiver is stopped
+[FAIL] setParameters must detect InvalidStateError synchronously always when transceiver is stopped
+  assert_equals: promise rejected on same task expected "rejected" but got "pending"
+[PASS] pc.getStats must detect InvalidAccessError synchronously always
+[FAIL] isOperationsChainEmpty detects empty in stable
+  assert_true: Empty to start expected true got false
+[FAIL] isOperationsChainEmpty detects empty in have-local-offer
+  assert_true: Empty to start expected true got false
+[FAIL] isOperationsChainEmpty detects empty in have-remote-offer
+  assert_equals: isOperationsChainEmpty is working expected "InvalidStateError" but got "Error"
+[PASS] createOffer uses operations chain
+[FAIL] createAnswer uses operations chain
+  assert_equals: isOperationsChainEmpty is working expected "InvalidStateError" but got "Error"
+[FAIL] setLocalDescription uses operations chain
+  assert_true: Empty before expected true got false
+[FAIL] setRemoteDescription uses operations chain
+  assert_true: Empty before expected true got false
+[FAIL] addIceCandidate uses operations chain
+  assert_equals: isOperationsChainEmpty is working expected "InvalidStateError" but got "Error"
+[FAIL] Firing of negotiationneeded does NOT use operations chain
+  assert_true: Empty chain expected true got false
+[PASS] Negotiationneeded only fires once operations chain is empty
+[FAIL] replaceTrack uses operations chain
+  assert_true: Empty chain expected true got false
+[FAIL] setParameters does NOT use the operations chain
+  assert_true: Empty chain expected true got false
+[FAIL] pc.getStats does NOT use the operations chain
+  assert_true: Empty chain expected true got false
+[FAIL] sender.getStats does NOT use the operations chain
+  assert_true: Empty chain expected true got false
+[FAIL] receiver.getStats does NOT use the operations chain
+  assert_true: Empty chain expected true got false
+[PASS] addIceCandidate chains onto SRD, fails before
+[PASS] Operations queue not vulnerable to recursion by chained negotiationneeded
+[FAIL] Pack operations queue with implicit offer and answer
+  promise_test: Unhandled rejection with value: object "OperationError: Failed to execute 'setLocalDescription' on 'RTCPeerConnection': Failed to parse SessionDescription.  Expect line: v="
+[TIMEOUT] Negotiate solely by operations queue and signaling state
+  Test timed out
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt
new file mode 100644
index 0000000..88def9a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to parse SessionDescription. Invalid SDP Expect line: v=
+[PASS] setRemoteDescription with valid offer should succeed
+[PASS] setRemoteDescription multiple times should succeed
+[PASS] setRemoteDescription multiple times with different offer should succeed
+[FAIL] setRemoteDescription(offer) with invalid SDP should reject with RTCError
+  assert_equals: Expect error detail field to set to sdp-syntax-error expected (string) "sdp-syntax-error" but got (undefined) undefined
+[PASS] setRemoteDescription(offer) from have-local-offer should roll back and succeed
+[FAIL] setRemoteDescription(offer) from have-local-offer fires signalingstatechange twice
+  assert_equals: expected null but got object "[object RTCSessionDescription]"
+[PASS] setRemoteDescription(offer) in stable should update internal state with a queued task, in the right order
+[FAIL] setRemoteDescription(offer) in have-local-offer should update internal state with a queued task, in the right order
+  assert_equals: pendingRemoteDescription should be updated before the signalingstatechange event expected null but got object "[object RTCSessionDescription]"
+[FAIL] Naive rollback approach is not glare-proof (control)
+  assert_unreached: Should have rejected: undefined Reached unreachable code
+[PASS] setRemoteDescription(offer) from have-local-offer is glare-proof
+[TIMEOUT] setRemoteDescription(invalidOffer) from have-local-offer does not undo rollback
+  Test timed out
+[NOTRUN] repeated sRD(offer) works
+[NOTRUN] sRD(reoffer) with candidates and without trickle works
+[NOTRUN] Transceivers added by sRD(offer) should not show up until sRD resolves
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/back-forward-cache-with-closed-webrtc-connection.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/back-forward-cache-with-closed-webrtc-connection.https.window-expected.txt
new file mode 100644
index 0000000..a6e09caa2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/back-forward-cache-with-closed-webrtc-connection.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Testing BFCache support for page with closed WebRTC connection.
+  BFCache not supported.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/back-forward-cache-with-open-webrtc-connection.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/back-forward-cache-with-open-webrtc-connection.https.window-expected.txt
new file mode 100644
index 0000000..fde9437f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webrtc/back-forward-cache-with-open-webrtc-connection.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Testing BFCache support for page with open WebRTC connection.
+  assert_true: Expected: WebRTC\nGot: WebRTC,internal-error\nMissing: \nExtra: internal-error\n expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/back-forward-cache-with-closed-websocket-connection.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/back-forward-cache-with-closed-websocket-connection.window-expected.txt
new file mode 100644
index 0000000..4e4acdbd3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/back-forward-cache-with-closed-websocket-connection.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Testing BFCache support for page with closed WebSocket connection.
+  BFCache not supported.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/back-forward-cache-with-open-websocket-connection.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/back-forward-cache-with-open-websocket-connection.window-expected.txt
new file mode 100644
index 0000000..bd231ae
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/back-forward-cache-with-open-websocket-connection.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Testing BFCache support for page with open WebSocket connection.
+  assert_true: Expected: websocket\nGot: internal-error,websocket\nMissing: \nExtra: internal-error\n expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webtransport/back-forward-cache-with-closed-webtransport-connection.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webtransport/back-forward-cache-with-closed-webtransport-connection.https.window-expected.txt
new file mode 100644
index 0000000..4629a07
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webtransport/back-forward-cache-with-closed-webtransport-connection.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[PRECONDITION_FAILED] Testing BFCache support for page with closed WebTransport connection.
+  BFCache not supported.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webusb/requestDevice/sandboxed_iframe.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webusb/requestDevice/sandboxed_iframe.https.window-expected.txt
new file mode 100644
index 0000000..ec57b6f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/webusb/requestDevice/sandboxed_iframe.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] RequestDevice from a sandboxed iframe is valid.
+  assert_equals: expected (object) object "[object Object]" but got (string) "FAIL: NotFoundError: Failed to execute 'requestDevice' on 'USB': No device selected."
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/window-management/multi-screen-window-open-fullscreen.tentative.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/window-management/multi-screen-window-open-fullscreen.tentative.https-expected.txt
new file mode 100644
index 0000000..ddbae0ab
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/window-management/multi-screen-window-open-fullscreen.tentative.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[PASS] Use multi-screen details to open a fullscreen popup window on each screen
+[FAIL] Open a fullscreen popup on '0'
+  assert_equals: popup: (250,250 300x100), 'undefined': (undefined,undefined 800x600) expected 0 but got 250
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/xhr/send-accept-language-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/xhr/send-accept-language-expected.txt
new file mode 100644
index 0000000..b53913750
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/xhr/send-accept-language-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Send "sensible" default value, whatever that means
+  assert_regexp_match: expected object "/Accept-Language:\s.+/" but got ""
+[PASS] XMLHttpRequest: send() - Accept-Language
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_annexb-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_annexb-expected.txt
new file mode 100644
index 0000000..5b37deb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_annexb-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+All subtests passed and are omitted for brevity.
+See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_hevc-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_hevc-expected.txt
new file mode 100644
index 0000000..5b37deb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any.worker_h265_hevc-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+All subtests passed and are omitted for brevity.
+See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_annexb-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_annexb-expected.txt
new file mode 100644
index 0000000..5b37deb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_annexb-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+All subtests passed and are omitted for brevity.
+See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_hevc-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_hevc-expected.txt
new file mode 100644
index 0000000..5b37deb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/virtual/webcodecs-without-task-runner-with-custom-deleter/external/wpt/webcodecs/videoDecoder-codec-specific.https.any_h265_hevc-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+All subtests passed and are omitted for brevity.
+See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/battery-status/no-gc-with-eventlisteners.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/battery-status/no-gc-with-eventlisteners.https-expected.txt
new file mode 100644
index 0000000..dd623dbe
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/battery-status/no-gc-with-eventlisteners.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] BatteryManager object is not garbage-collected with listeners attached
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/battery-status/no-gc-with-pending-promise.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/battery-status/no-gc-with-pending-promise.https-expected.txt
new file mode 100644
index 0000000..34aac9c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/battery-status/no-gc-with-pending-promise.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] navigator.getBattery() should resolve even in the face of GC
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/clipboard-apis/async-custom-format-write-read.tentative.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/clipboard-apis/async-custom-format-write-read.tentative.https-expected.txt
new file mode 100644
index 0000000..3a2a5268
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/clipboard-apis/async-custom-format-write-read.tentative.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verify write and read clipboard given web custom format as input
+  assert_equals: expected "Test text." but got ""
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/clipboard-apis/async-custom-formats-write-read.tentative.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/clipboard-apis/async-custom-formats-write-read.tentative.https-expected.txt
new file mode 100644
index 0000000..4a86b32
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/clipboard-apis/async-custom-formats-write-read.tentative.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verify write and read clipboard given 2 platform-neutral custom format inputs
+  assert_equals: expected "input data 1" but got ""
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/report-to-directive-allowed-in-meta.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/report-to-directive-allowed-in-meta.https.sub-expected.txt
new file mode 100644
index 0000000..aa0615a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/report-to-directive-allowed-in-meta.https.sub-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Test that image does not load
+[PASS] Event is fired
+[PASS] Report is observable to ReportingObserver
+[FAIL] Violation report status OK.
+  Cannot read properties of undefined (reading 'body')
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/reporting-api-report-only-sends-reports-on-violation.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/reporting-api-report-only-sends-reports-on-violation.https.sub-expected.txt
new file mode 100644
index 0000000..5353d7fc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/reporting-api-report-only-sends-reports-on-violation.https.sub-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PASS] Test that image does not load
+[PASS] Event is fired
+[FAIL] Violation report status OK.
+  Cannot read properties of undefined (reading 'body')
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub-expected.txt
new file mode 100644
index 0000000..aa0615a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/reporting-api-sends-reports-on-violation.https.sub-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Test that image does not load
+[PASS] Event is fired
+[PASS] Report is observable to ReportingObserver
+[FAIL] Violation report status OK.
+  Cannot read properties of undefined (reading 'body')
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/reporting-api-works-on-frame-src.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/reporting-api-works-on-frame-src.https.sub-expected.txt
new file mode 100644
index 0000000..674016d8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/content-security-policy/reporting-api/reporting-api-works-on-frame-src.https.sub-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[PASS] Event is fired
+[FAIL] Violation report status OK.
+  Cannot read properties of undefined (reading 'body')
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/credential-management/fedcm-3pc-blocked-with-iss-3p-ot.sub.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/credential-management/fedcm-3pc-blocked-with-iss-3p-ot.sub.https-expected.txt
new file mode 100644
index 0000000..bb52b12
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/credential-management/fedcm-3pc-blocked-with-iss-3p-ot.sub.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: testRunner is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/credential-management/fedcm-3pc-blocked-with-iss-ot.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/credential-management/fedcm-3pc-blocked-with-iss-ot.https-expected.txt
new file mode 100644
index 0000000..bb52b12
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/credential-management/fedcm-3pc-blocked-with-iss-ot.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: testRunner is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/css/css-borders/subpixel-border-width-value-recomputed-when-zoom-changes-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/css/css-borders/subpixel-border-width-value-recomputed-when-zoom-changes-expected.txt
new file mode 100644
index 0000000..17d6046a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/css/css-borders/subpixel-border-width-value-recomputed-when-zoom-changes-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Border width responsive to zoom changes
+  testRunner is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/css/css-fonts/font-size-adjust-with-zoom-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/css/css-fonts/font-size-adjust-with-zoom-expected.txt
new file mode 100644
index 0000000..007e25d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/css/css-fonts/font-size-adjust-with-zoom-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[PASS] 1ex equal to the original font-size.
+[FAIL] 1ex equal to the original font-size - 200% page zoom.
+  assert_true: window.testRunner is required for this test. expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/digital-goods/digital-goods-interface.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/digital-goods/digital-goods-interface.https-expected.txt
new file mode 100644
index 0000000..a993504
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/digital-goods/digital-goods-interface.https-expected.txt
@@ -0,0 +1,21 @@
+This is a testharness.js-based test.
+[PASS] Digital goods service exists.
+[PASS] Digital goods service is available.
+[PASS] Digital goods service rejects for empty payment method.
+[PASS] Digital goods service rejects for unknown payment method.
+[PASS] Digital goods service rejects from within cross-site iframe.
+[PASS] Digital goods service passes same-site check from within subdomain iframe.
+[PASS] GetDetails round trip, required fields.
+[PASS] GetDetails round trip, optional fields.
+[PASS] GetDetails multiple IDs.
+[PASS] GetDetails no IDs should error.
+[PASS] GetDetails none found.
+[PASS] GetDetails not all found.
+[PASS] GetDetails internal error.
+[PASS] Consume a purchase token.
+[PASS] Consume with bad purchase token should error.
+[PASS] ListPurchases round trip.
+[PASS] ListPurchaseHistory round trip.
+[FAIL] DigitalGoods referenced by scripts should survive garbage collector.
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-001-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-001-expected.txt
new file mode 100644
index 0000000..169619d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-001-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Nodes in a content-visibility auto tree are exposed to accessibility tree
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-002-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-002-expected.txt
new file mode 100644
index 0000000..6558ec6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-002-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Nodes in hidden non-activatable tree are not exposed to accessibility tree
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003-expected.txt
new file mode 100644
index 0000000..71836a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Accessiblility focus causes activatable hidden tree to activate
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003a-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003a-expected.txt
new file mode 100644
index 0000000..6251992c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003a-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] A11y tree is updated after ContentVisibilityAutoStateChange fires when element gains focus via element.focus()
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003b-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003b-expected.txt
new file mode 100644
index 0000000..bca6da40
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003b-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] A11y tree is updated after ContentVisibilityAutoStateChange fires when element gains focus from a11y focus action
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003c-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003c-expected.txt
new file mode 100644
index 0000000..cee7e88
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-003c-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] DOM focus causes activatable hidden tree to activate
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-004-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-004-expected.txt
new file mode 100644
index 0000000..81b24b2f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-004-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Accessiblility press() causes activatable hidden tree to activate
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-005-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-005-expected.txt
new file mode 100644
index 0000000..bfc47bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-005-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Accessiblility scrollToMakeVisible() causes activatable hidden tree to activate
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-006-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-006-expected.txt
new file mode 100644
index 0000000..2c3034b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-006-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Accessiblility name calculation on child of content-visibility: auto does not destroy tree
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-007-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-007-expected.txt
new file mode 100644
index 0000000..749acc8a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-007-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Accessiblility with forced layout does not recreate subtree
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-008-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-008-expected.txt
new file mode 100644
index 0000000..b2f298e5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-008-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] When hidden is added, nodes in non-activatable tree are not exposed to accessibility tree
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-009-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-009-expected.txt
new file mode 100644
index 0000000..bd7000a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-009-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] aria labels inside hidden=until-found subtrees should still work.
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-display-none-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-display-none-expected.txt
new file mode 100644
index 0000000..fd1066a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/accessibility/content-visibility-accessibility-display-none-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Verifies that display:none elements can't have children in the accessibility tree due to content-visibility:auto.
+  accessibilityController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/content-visibility-event-sender-001-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/content-visibility-event-sender-001-expected.txt
new file mode 100644
index 0000000..188cd3e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/content-visibility-event-sender-001-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: eventSender is not defined
+[TIMEOUT] Using tab navigation to target an element in an auto subtree focuses element
+  Test timed out
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/content-visibility-event-sender-002-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/content-visibility-event-sender-002-expected.txt
new file mode 100644
index 0000000..ec59e390
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/display-lock/css-content-visibility/content-visibility-event-sender-002-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Trying to focus on an element in a locked subtree that's not visible will skip that element
+  eventSender is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/dom/abort/abort-signal-any-internal-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/dom/abort/abort-signal-any-internal-expected.txt
new file mode 100644
index 0000000..6eacf44
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/dom/abort/abort-signal-any-internal-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] abort-signal-any-internal
+  gc is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/dom/abort/abort-signal-memory-tests.https.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/dom/abort/abort-signal-memory-tests.https.any-expected.txt
new file mode 100644
index 0000000..c3252b9b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/dom/abort/abort-signal-memory-tests.https.any-expected.txt
@@ -0,0 +1,28 @@
+This is a testharness.js-based test.
+[FAIL] Controllers can be GCed when their signals are being followed (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort sources have been GCed (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or event listeners (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or relevant event listeners (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort event listeners have been removed (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals are not GCed before being aborted by a controller when they have abort event listeners (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Composite signals are not GCed before being aborted by timeout when they have abort event listeners (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Temporary composite signals used for constructing other composite signals can be GCed (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Nested and intermediate composite signals can be GCed when expected (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Settled composite signals with event listeners can be GCed (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] AbortSignalRegistry tracks algorithm handles for event listeners
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] AbortSignalRegistry tracks algorithm handles for event listeners (composite signal)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Lock request keeps composite signal alive
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/dom/abort/abort-signal-memory-tests.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/dom/abort/abort-signal-memory-tests.https.any.worker-expected.txt
new file mode 100644
index 0000000..c3252b9b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/dom/abort/abort-signal-memory-tests.https.any.worker-expected.txt
@@ -0,0 +1,28 @@
+This is a testharness.js-based test.
+[FAIL] Controllers can be GCed when their signals are being followed (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort sources have been GCed (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or event listeners (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or relevant event listeners (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort event listeners have been removed (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals are not GCed before being aborted by a controller when they have abort event listeners (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Composite signals are not GCed before being aborted by timeout when they have abort event listeners (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Temporary composite signals used for constructing other composite signals can be GCed (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Nested and intermediate composite signals can be GCed when expected (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Settled composite signals with event listeners can be GCed (using AbortSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] AbortSignalRegistry tracks algorithm handles for event listeners
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] AbortSignalRegistry tracks algorithm handles for event listeners (composite signal)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Lock request keeps composite signal alive
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/encoding/supported-encodings.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/encoding/supported-encodings.window-expected.txt
new file mode 100644
index 0000000..f5a0dd38a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/encoding/supported-encodings.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: internals is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/fetch/fetch-later/send-on-deactivate-with-background-sync.tentative.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/fetch/fetch-later/send-on-deactivate-with-background-sync.tentative.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/fetch/fetch-later/send-on-deactivate-with-background-sync.tentative.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-click-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-click-expected.txt
new file mode 100644
index 0000000..a016460
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-click-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] clicking on a file input element launches a file chooser
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-key-enter-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-key-enter-expected.txt
new file mode 100644
index 0000000..70830b0d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-key-enter-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] pressing Enter key with focus on a file input launches a file chooser
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-key-other-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-key-other-expected.txt
new file mode 100644
index 0000000..1fb5fa8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-key-other-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] pressing a key other than Enter or Space with focus on a file input does not launch a file chooser
+  eventSender is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-key-space-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-key-space-expected.txt
new file mode 100644
index 0000000..090b629
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-key-space-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] pressing the Space key with a file input focused launches a file chooser
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-click-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-click-expected.txt
new file mode 100644
index 0000000..1ed5493
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-click-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] clicking a file input with the webkitdirectory attribute launches a file chooser
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-enter-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-enter-expected.txt
new file mode 100644
index 0000000..505dcc61
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-enter-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] pressing Enter with focus on a webkitdirectory file input element launches a file chooser
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-enter-prevent-keypress-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-enter-prevent-keypress-expected.txt
new file mode 100644
index 0000000..c9f3cb4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-enter-prevent-keypress-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] pressing Enter with a webkitdirectory file input focused still launches a file chooser if preventDefault() is called on the keypress event
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-enter-prevent-keyup-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-enter-prevent-keyup-expected.txt
new file mode 100644
index 0000000..fb546f0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-enter-prevent-keyup-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] pressing Enter on a focused webkitdirectory file input does not show a chooser if keyup on the element is handled with preventDefault()
+  eventSender is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-other-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-other-expected.txt
new file mode 100644
index 0000000..17744cb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-other-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] pressing a key other than Enter or Space with focus on a webkitdirectory file input element does not launch a chooser
+  eventSender is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-space-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-space-expected.txt
new file mode 100644
index 0000000..55620ff7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-input-webkitdirectory-key-space-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] pressing Space on a focused webkitdirectory file input element launches a file chooser
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-webkitRelativePath-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-webkitRelativePath-expected.txt
new file mode 100644
index 0000000..ff954c3c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-webkitRelativePath-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] webkitRelativePath is relative from the to the parent of the chosen non-root directory
+  promise_test: Unhandled rejection with value: object "ReferenceError: internals is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-webkitRelativePath-root-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-webkitRelativePath-root-expected.txt
new file mode 100644
index 0000000..ed9b74c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/forms/file/file-webkitRelativePath-root-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] webkitRelativePath is relative to the selected root directory
+  promise_test: Unhandled rejection with value: object "ReferenceError: internals is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/generic-sensor/lose-focus-suspend-readings.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/generic-sensor/lose-focus-suspend-readings.https.window-expected.txt
new file mode 100644
index 0000000..3da2b12
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/generic-sensor/lose-focus-suspend-readings.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Losing focus must cause readings to be suspended
+  assert_implements: window.internals is required undefined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/geolocation-api/getCurrentPosition_visibility.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/geolocation-api/getCurrentPosition_visibility.https-expected.txt
new file mode 100644
index 0000000..9d4eb027
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/geolocation-api/getCurrentPosition_visibility.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] getCurrentPosition returns after visibilityState changes
+  promise_test: Unhandled rejection with value: object "ReferenceError: testRunner is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/geolocation-api/watchPosition-page-visibility.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/geolocation-api/watchPosition-page-visibility.https-expected.txt
new file mode 100644
index 0000000..558bbef
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/geolocation-api/watchPosition-page-visibility.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: testRunner is not defined
+[TIMEOUT] Tests that watchPosition does not report position changes when the page is not visible.
+  Test timed out
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/hid/hidDevice_detachedFrame.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/hid/hidDevice_detachedFrame.https.window-expected.txt
new file mode 100644
index 0000000..854e2cd5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/hid/hidDevice_detachedFrame.https.window-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] open() rejects in a detached context
+  promise_test: Unhandled rejection with value: object "ReferenceError: GCController is not defined"
+[FAIL] forget() rejects in a detached context
+  promise_test: Unhandled rejection with value: object "ReferenceError: GCController is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/hid/requestDevice/sandboxed_iframe.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/hid/requestDevice/sandboxed_iframe.https.window-expected.txt
new file mode 100644
index 0000000..dcaaa6ae
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/hid/requestDevice/sandboxed_iframe.https.window-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught Error: assert_equals: expected (string) "Success" but got (object) object "[object Object]"
+[TIMEOUT] Calls to HID APIs from a sandboxed iframe are valid.
+  Test timed out
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-embedder-policy/reporting-to-endpoint.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-embedder-policy/reporting-to-endpoint.https-expected.txt
new file mode 100644
index 0000000..7b516fd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-embedder-policy/reporting-to-endpoint.https-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+[FAIL] subresource CORP
+  assert_unreached: A report whose blockedURL is https://www1.web-platform.test:8444/common/text-plain.txt and url is https://web-platform.test:8444/wpt_internal/html/cross-origin-embedder-policy/resources/reporting-empty-frame.html?pipe=header(cross-origin-embedder-policy,require-corp;report-to=%22endpoint%22)|header(cross-origin-embedder-policy-report-only,require-corp;report-to=%22report-only-endpoint%22) is not found. Reached unreachable code
+[FAIL] navigation CORP
+  assert_unreached: A report whose blockedURL is https://www1.web-platform.test:8444/common/blank.html and url is https://web-platform.test:8444/wpt_internal/html/cross-origin-embedder-policy/resources/reporting-empty-frame.html?pipe=header(cross-origin-embedder-policy,require-corp;report-to=%22endpoint%22)|header(cross-origin-embedder-policy-report-only,require-corp;report-to=%22report-only-endpoint%22) is not found. Reached unreachable code
+[FAIL] COEP violation on nested frame navigation
+  assert_unreached: A report whose blockedURL is https://web-platform.test:8444/common/blank.html and url is https://web-platform.test:8444/wpt_internal/html/cross-origin-embedder-policy/resources/reporting-empty-frame.html?pipe=header(cross-origin-embedder-policy,require-corp;report-to=%22endpoint%22)|header(cross-origin-embedder-policy-report-only,require-corp;report-to=%22report-only-endpoint%22) is not found. Reached unreachable code
+[FAIL] Two COEP headers, split inside report-to value
+  assert_unreached: A report whose blockedURL is https://web-platform.test:8444/common/blank.html and url is https://web-platform.test:8444/wpt_internal/html/cross-origin-embedder-policy/resources/reporting-empty-frame-multiple-headers.html.asis is not found. Reached unreachable code
+[FAIL] Shared worker fetch
+  assert_unreached: A report whose blockedURL is https://www1.web-platform.test:8444/common/blank.html and url is https://web-platform.test:8444/wpt_internal/html/cross-origin-embedder-policy/resources/shared-worker.js?pipe=header(cross-origin-embedder-policy,require-corp;report-to=%22endpoint%22)|header(cross-origin-embedder-policy-report-only,require-corp;report-to=%22report-only-endpoint%22) is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https-expected.txt
new file mode 100644
index 0000000..c611ffc0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] coop reporting test A test with both COOP and COOP report only setup to CROSS_ORIGIN with same-origin-allow-popups; report-to="coop-popup-report-endpoint", require-corp, same-origin; report-to="coop-popup-report-only-endpoint", require-corp
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-allow-popups\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-four-reports.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https-expected.txt
new file mode 100644
index 0000000..6fe2b203
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with , , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-only-endpoint, expected report: {\"body\":{\"disposition\":\"reporting\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-only-endpoint, expected report: {\"body\":{\"disposition\":\"reporting\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/report-only-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] coop reporting test reporting same origin with report-to to SAME_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", 
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https-expected.txt
new file mode 100644
index 0000000..37fee1c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-popup.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] Open a popup to a document without COOP, then navigate it to a document with
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-popup-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"unsafe-none\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"/uuid=(uuid)$/\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https-expected.txt
new file mode 100644
index 0000000..aeb0bdc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-allow-popups\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with same-origin-allow-popups; report-to="coop-popup-report-endpoint", require-corp, , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-allow-popups\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with same-origin, require-corp, , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-allow-popups\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-allow-popups-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https-expected.txt
new file mode 100644
index 0000000..89a0be73
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+[PASS] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", require-corp, , 
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-plus-coep\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", require-corp, , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-plus-coep\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", require-corp
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-plus-coep\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with , , same-origin; report-to="coop-popup-report-only-endpoint", require-corp
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin-plus-coep\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-coep-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https-expected.txt
new file mode 100644
index 0000000..e397e7f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https-expected.txt
@@ -0,0 +1,14 @@
+This is a testharness.js-based test.
+[PASS] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with unsafe-none; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", require-corp, , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with unsafe-none; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with unsafe-none, , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"same-origin\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-same-origin-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https-expected.txt
new file mode 100644
index 0000000..3d0da47
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"unsafe-none\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to SAME_ORIGIN with same-origin, , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"unsafe-none\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[FAIL] coop reporting test reporting same origin with report-to to CROSS_ORIGIN with same-origin; report-to="coop-popup-report-endpoint", , , 
+  promise_test: Unhandled rejection with value: "No report matched the expected report for endpoint: coop-report-endpoint, expected report: {\"body\":{\"disposition\":\"enforce\",\"effectivePolicy\":\"unsafe-none\",\"nextResponseURL\":\"/uuid=(uuid)$/\",\"type\":\"navigation-from-response\"},\"url\":\"https://web-platform.test:8444/wpt_internal/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-popup-unsafe-none-report-to.https.html\",\"type\":\"coop\"}, within available reports: []"
+[PASS] verify remaining reports
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/interaction/focus/the-autofocus-attribute/object-fallback-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/interaction/focus/the-autofocus-attribute/object-fallback-expected.txt
new file mode 100644
index 0000000..55491c5b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/interaction/focus/the-autofocus-attribute/object-fallback-expected.txt
@@ -0,0 +1,12 @@
+This is a testharness.js-based test.
+[FAIL] An autofocus element in an OBJECT with a loaded frame should not be processed
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] An autofocus element in an OBJECT with a load-failed frame should be processed
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] An autofocus element in an OBJECT with a loaded image should not be processed
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] An autofocus element in an OBJECT with a load-failed image should be processed
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] An autofocus element in nested OBJECTs with load-failed images should be processed
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/rendering/non-replaced-elements/textarea-centering-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/rendering/non-replaced-elements/textarea-centering-expected.txt
new file mode 100644
index 0000000..29f0d74
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/html/rendering/non-replaced-elements/textarea-centering-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Resizing a centered textarea should remain centered.
+  eventSender is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/js/async-gc-leak-test-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/js/async-gc-leak-test-expected.txt
new file mode 100644
index 0000000..3c93941
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/js/async-gc-leak-test-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Async gc() should not cause a leak
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/long-animation-frame/loaf-ukm-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/long-animation-frame/loaf-ukm-expected.txt
new file mode 100644
index 0000000..b6f2fc9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/long-animation-frame/loaf-ukm-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] UKM recorder should receive LoAF entries
+  promise_test: Unhandled rejection with value: object "ReferenceError: internals is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/long-animation-frame/loaf-use-counter-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/long-animation-frame/loaf-use-counter-expected.txt
new file mode 100644
index 0000000..974a91b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/long-animation-frame/loaf-use-counter-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[FAIL] UseCounter for LoAF should not be triggered for non-loaf types
+  promise_test: Unhandled rejection with value: object "ReferenceError: internals is not defined"
+[FAIL] UseCounter for LoAF requested should be triggered at appropriate times
+  promise_test: Unhandled rejection with value: object "ReferenceError: internals is not defined"
+[FAIL] UseCounter for LoAF observer should be triggered at appropriate times
+  promise_test: Unhandled rejection with value: object "ReferenceError: internals is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/mediacapture-extensions/MediaStreamTrack-configurationchange.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/mediacapture-extensions/MediaStreamTrack-configurationchange.https.window-expected.txt
new file mode 100644
index 0000000..a11b39d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/mediacapture-extensions/MediaStreamTrack-configurationchange.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Identifier 'MessageQueue' has already been declared
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/mediacapture-handle/identity/MediaDevices-setCaptureHandleConfig_detachedFrame.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/mediacapture-handle/identity/MediaDevices-setCaptureHandleConfig_detachedFrame.https.window-expected.txt
new file mode 100644
index 0000000..3b1a0e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/mediacapture-handle/identity/MediaDevices-setCaptureHandleConfig_detachedFrame.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] setCaptureHandleConfig raises InvalidStateError in a detached context.
+  GCController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker-expected.txt
new file mode 100644
index 0000000..5a6ad69
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught TypeError: Cannot read properties of undefined (reading 'getReader')
+[PASS] Test we can transfer a Video MediaStreamTrackProcessor stream
+[PASS] Test we can transfer an Audio MediaStreamTrackProcessor stream
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/messaging/message-port-memory.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/messaging/message-port-memory.any-expected.txt
new file mode 100644
index 0000000..0316ef8a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/messaging/message-port-memory.any-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Message ports get GCed after they are no longer referenced.
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/messaging/message-port-memory.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/messaging/message-port-memory.any.worker-expected.txt
new file mode 100644
index 0000000..0316ef8a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/messaging/message-port-memory.any.worker-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Message ports get GCed after they are no longer referenced.
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/navigation-api/navigate-from-initial-about-blank-gc-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/navigation-api/navigate-from-initial-about-blank-gc-expected.txt
new file mode 100644
index 0000000..e9716cd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/navigation-api/navigate-from-initial-about-blank-gc-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] navigate() from <iframe> with src="" but still on initial about:blank doesn't cause a crash on GC
+  promise_test: Unhandled rejection with value: object "ReferenceError: internals is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/observable/subscriber-weak-ref-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/observable/subscriber-weak-ref-expected.txt
new file mode 100644
index 0000000..069c2c3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/observable/subscriber-weak-ref-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Subscriber is not arbitrarily kept alive until the subscription ends, but can be garbage collected if it is weakly owned throughout the subscription
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/observable/use-counter-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/observable/use-counter-expected.txt
new file mode 100644
index 0000000..75f8596
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/observable/use-counter-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] use-counter
+  internals is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any-expected.txt
new file mode 100644
index 0000000..4de7df7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] unrestricted-sab-enabled
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any.serviceworker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any.serviceworker-expected.txt
new file mode 100644
index 0000000..4de7df7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any.serviceworker-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] unrestricted-sab-enabled
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any.sharedworker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any.sharedworker-expected.txt
new file mode 100644
index 0000000..4de7df7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any.sharedworker-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] unrestricted-sab-enabled
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any.worker-expected.txt
new file mode 100644
index 0000000..4de7df7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/origin_trials/unrestricted_shared_array_buffer/unrestricted-sab-enabled.https.any.worker-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] unrestricted-sab-enabled
+  assert_true: expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/payments/promises-keep-request-alive.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/payments/promises-keep-request-alive.https-expected.txt
new file mode 100644
index 0000000..b77be38
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/payments/promises-keep-request-alive.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Promises resolve even without references to request or response.
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/performance-timeline/performance-user-timing-special-names-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/performance-timeline/performance-user-timing-special-names-expected.txt
new file mode 100644
index 0000000..3c0ce35
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/performance-timeline/performance-user-timing-special-names-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Test named 'Performance measure processes special names that are defined in User Timing API' specified 1 'cleanup' function, and 1 failed.
+[FAIL] Performance measure processes special names that are defined in User Timing API
+  internals is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/prerender/focus-on-prerendered-window-client.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/prerender/focus-on-prerendered-window-client.https-expected.txt
new file mode 100644
index 0000000..bb52b12
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/prerender/focus-on-prerendered-window-client.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: testRunner is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/presentation/presentation-onreceiverconnection.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/presentation/presentation-onreceiverconnection.https-expected.txt
new file mode 100644
index 0000000..20753658
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/presentation/presentation-onreceiverconnection.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test presentation.receiver.connectionList resolves with incoming connection.
+  promise_test: Unhandled rejection with value: object "ReferenceError: internals is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/presentation/presentationrequest-gc.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/presentation/presentationrequest-gc.https-expected.txt
new file mode 100644
index 0000000..d9c445f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/presentation/presentationrequest-gc.https-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: gc is not defined
+[PASS] Test that a PresentationRequest is not garbage collected while getAvailability() is pending.
+[FAIL] Test that navigator.presentation.defaultRequest.onconnectionavailable with one URL isn't reset after gc().
+  gc is not defined
+[FAIL] Test that navigator.presentation.defaultRequest.onconnectionavailable with multiple URLs isn't reset after gc().
+  gc is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/cross-origin-report-no-credentials-report-to.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/cross-origin-report-no-credentials-report-to.https.sub-expected.txt
new file mode 100644
index 0000000..4c072fb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/cross-origin-report-no-credentials-report-to.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Reporting endpoints did not receive credentials.
+  assert_unreached: A report of csp-violation from https://web-platform.test:8444/wpt_internal/reporting/cross-origin-report-no-credentials-report-to.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/deprecation-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/deprecation-expected.txt
new file mode 100644
index 0000000..f855f76
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/deprecation-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Deprecation reports
+  internals is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/intervention-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/intervention-expected.txt
new file mode 100644
index 0000000..2c39de8a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/intervention-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Intervention report
+  internals is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/path-absolute-endpoint.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/path-absolute-endpoint.https.sub-expected.txt
new file mode 100644
index 0000000..3de209a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/path-absolute-endpoint.https.sub-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+[PASS] Test that image does not load
+[PASS] Event is fired
+[PASS] Report is observable to ReportingObserver
+[FAIL] Reporting endpoints received reports.
+  assert_unreached: A report of csp-violation from https://web-platform.test:8444/wpt_internal/reporting/path-absolute-endpoint.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/same-origin-report-no-credentials-report-to.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/same-origin-report-no-credentials-report-to.https.sub-expected.txt
new file mode 100644
index 0000000..490b0822
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/reporting/same-origin-report-no-credentials-report-to.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Reporting endpoints did not receive credentials.
+  assert_unreached: A report of csp-violation from https://web-platform.test:8444/wpt_internal/reporting/same-origin-report-no-credentials-report-to.https.sub.html is not found. Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/resource-timing/initiator-type-early-hints-preload.h2.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/resource-timing/initiator-type-early-hints-preload.h2.window-expected.txt
new file mode 100644
index 0000000..2796db94
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/resource-timing/initiator-type-early-hints-preload.h2.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Ensure initiatorType is set to 'early-hints'
+  internals is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-1.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-1.any-expected.txt
new file mode 100644
index 0000000..8f0a51d2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-1.any-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+[FAIL] Controllers can be GCed when their signals are being followed (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort sources have been GCed (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or event listeners (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or relevant event listeners (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort event listeners have been removed (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals are not GCed before being aborted by a controller when they have abort event listeners (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Composite signals are not GCed before being aborted by timeout when they have abort event listeners (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Temporary composite signals used for constructing other composite signals can be GCed (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Nested and intermediate composite signals can be GCed when expected (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Settled composite signals with event listeners can be GCed (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-1.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-1.any.worker-expected.txt
new file mode 100644
index 0000000..8f0a51d2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-1.any.worker-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+[FAIL] Controllers can be GCed when their signals are being followed (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort sources have been GCed (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or event listeners (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or relevant event listeners (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort event listeners have been removed (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals are not GCed before being aborted by a controller when they have abort event listeners (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Composite signals are not GCed before being aborted by timeout when they have abort event listeners (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Temporary composite signals used for constructing other composite signals can be GCed (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Nested and intermediate composite signals can be GCed when expected (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Settled composite signals with event listeners can be GCed (using TaskSignal and AbortController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-2.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-2.any-expected.txt
new file mode 100644
index 0000000..8aa70d95
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-2.any-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+[FAIL] Controllers can be GCed when their signals are being followed (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort sources have been GCed (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or event listeners (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or relevant event listeners (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort event listeners have been removed (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals are not GCed before being aborted by a controller when they have abort event listeners (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Composite signals are not GCed before being aborted by timeout when they have abort event listeners (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Temporary composite signals used for constructing other composite signals can be GCed (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Nested and intermediate composite signals can be GCed when expected (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Settled composite signals with event listeners can be GCed (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-2.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-2.any.worker-expected.txt
new file mode 100644
index 0000000..8aa70d95
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-abort-2.any.worker-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+[FAIL] Controllers can be GCed when their signals are being followed (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort sources have been GCed (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or event listeners (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when they have no references or relevant event listeners (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals can be GCed when all abort event listeners have been removed (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Signals are not GCed before being aborted by a controller when they have abort event listeners (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Composite signals are not GCed before being aborted by timeout when they have abort event listeners (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Temporary composite signals used for constructing other composite signals can be GCed (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Nested and intermediate composite signals can be GCed when expected (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Settled composite signals with event listeners can be GCed (using TaskSignal and TaskController)
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-priority.any-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-priority.any-expected.txt
new file mode 100644
index 0000000..cf95975
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-priority.any-expected.txt
@@ -0,0 +1,14 @@
+This is a testharness.js-based test.
+[FAIL] TaskSignals can be GCed when they have no references or event listeners
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] A TaskSignal with a prioritychange listener can be GCed when its priority source has been GCed
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] TaskSignals with prioritychange listeners are not GCed if their priority source is alive
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] TaskSignals with prioritychange listeners are not GCed after their abort source is GCed if their priority source is alive
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] TaskSignals with prioritychange listeners are not GCed after they are aborted if their priority source is alive
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Composite TaskSignals with pending tasks are not GCed if their priority source is alive
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-priority.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-priority.any.worker-expected.txt
new file mode 100644
index 0000000..cf95975
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/scheduler/task-signal-any-memory-priority.any.worker-expected.txt
@@ -0,0 +1,14 @@
+This is a testharness.js-based test.
+[FAIL] TaskSignals can be GCed when they have no references or event listeners
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] A TaskSignal with a prioritychange listener can be GCed when its priority source has been GCed
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] TaskSignals with prioritychange listeners are not GCed if their priority source is alive
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] TaskSignals with prioritychange listeners are not GCed after their abort source is GCed if their priority source is alive
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] TaskSignals with prioritychange listeners are not GCed after they are aborted if their priority source is alive
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+[FAIL] Composite TaskSignals with pending tasks are not GCed if their priority source is alive
+  promise_test: Unhandled rejection with value: object "ReferenceError: gc is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/serial/serialPort_detachedFrame.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/serial/serialPort_detachedFrame.https.window-expected.txt
new file mode 100644
index 0000000..854e2cd5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/serial/serialPort_detachedFrame.https.window-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] open() rejects in a detached context
+  promise_test: Unhandled rejection with value: object "ReferenceError: GCController is not defined"
+[FAIL] forget() rejects in a detached context
+  promise_test: Unhandled rejection with value: object "ReferenceError: GCController is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/serial/serialPort_readable_gc.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/serial/serialPort_readable_gc.https.window-expected.txt
new file mode 100644
index 0000000..1c8138a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/serial/serialPort_readable_gc.https.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Dropping references to a port does not close its streams
+  promise_test: Unhandled rejection with value: object "ReferenceError: GCController is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/serial/serial_detachedFrame.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/serial/serial_detachedFrame.https.window-expected.txt
new file mode 100644
index 0000000..2f435b3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/serial/serial_detachedFrame.https.window-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+[FAIL] getPorts() rejects in a detached context
+  promise_test: Unhandled rejection with value: object "ReferenceError: GCController is not defined"
+[FAIL] requestPort() rejects in a detached context
+  promise_test: Unhandled rejection with value: object "ReferenceError: GCController is not defined"
+[FAIL] adding an event listener does nothing in a detached context
+  promise_test: Unhandled rejection with value: object "ReferenceError: GCController is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/service-worker/storage-deprecation-trial-enabled.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/service-worker/storage-deprecation-trial-enabled.https-expected.txt
new file mode 100644
index 0000000..d37a2f4c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/service-worker/storage-deprecation-trial-enabled.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] Services workers under different top-level sites are not partitioned when the deprecation trial is enabled.
+  assert_false: The 1p iframe saw a pending promise in the service worker. expected false got true
+[FAIL] Services workers with cross-site ancestors are not partitioned when the deprecation trial is enabled.
+  assert_false: The 1p iframe saw a pending promise in the service worker. expected false got true
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/shadow-dom/shadow-dom-usecounter-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/shadow-dom/shadow-dom-usecounter-expected.txt
new file mode 100644
index 0000000..9f09fd2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/shadow-dom/shadow-dom-usecounter-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Attributes should not be counted in user agent shadow DOM.
+  internals is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/soft-navigation-heuristics/browser-initiated-popstate.tentative-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/soft-navigation-heuristics/browser-initiated-popstate.tentative-expected.txt
new file mode 100644
index 0000000..c800268
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/soft-navigation-heuristics/browser-initiated-popstate.tentative-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: testRunner is not defined
+[TIMEOUT] A soft navigation that uses a *browser initiated* popstate event is recognized by SoftNavigationHeuristics
+  Test timed out
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/system-wake-lock/idlharness-worker.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/system-wake-lock/idlharness-worker.https.window-expected.txt
new file mode 100644
index 0000000..4abf76bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/system-wake-lock/idlharness-worker.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 612, in do_testharness\n    done, rv = handler(result)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py", line 738, in __call__\n    return callback(url, payload)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py", line 753, in process_action\n    with ActionContext(self.logger, self.protocol, payload.get("context")):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py", line 795, in __enter__\n    self.protocol.testdriver.switch_to_window(self.context, self.initial_window)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py", line 501, in switch_to_window\n    raise Exception("Window with id %s not found" % wptrunner_id)\nException: Window with id False not found\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/system-wake-lock/idlharness.https.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/system-wake-lock/idlharness.https.window-expected.txt
new file mode 100644
index 0000000..4abf76bd
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/system-wake-lock/idlharness.https.window-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 612, in do_testharness\n    done, rv = handler(result)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py", line 738, in __call__\n    return callback(url, payload)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py", line 753, in process_action\n    with ActionContext(self.logger, self.protocol, payload.get("context")):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py", line 795, in __enter__\n    self.protocol.testdriver.switch_to_window(self.context, self.initial_window)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py", line 501, in switch_to_window\n    raise Exception("Window with id %s not found" % wptrunner_id)\nException: Window with id False not found\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/ukm/ukm-get-metrics-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/ukm/ukm-get-metrics-expected.txt
new file mode 100644
index 0000000..c740535
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/ukm/ukm-get-metrics-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] UKM recorder should receive the Blink.UpdateTime entry
+  promise_test: Unhandled rejection with value: object "ReferenceError: internals is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/user-timing/detail-isolated-world-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/user-timing/detail-isolated-world-expected.txt
new file mode 100644
index 0000000..ff8b09d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/user-timing/detail-isolated-world-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] A clone should be used in an isolated world, but only one clone
+  promise_test: Unhandled rejection with value: object "ReferenceError: testRunner is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/vibration/vibration-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/vibration/vibration-expected.txt
new file mode 100644
index 0000000..126f444
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/vibration/vibration-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[PASS] VibrationManager Mojo bindings and mock interfaces are available to tests.
+[FAIL] navigator.vibrate(1234) triggers vibration correctly.
+  assert_equals: expected (string) "Vibrate" but got (object) object "[object Object]"
+[PASS] navigator.vibrate(0) triggers cancel correctly.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/vibration/vibration-iframe-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/vibration/vibration-iframe-expected.txt
new file mode 100644
index 0000000..65f243b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/vibration/vibration-iframe-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: debug is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-locks/storage-deprecation-trial-enabled.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-locks/storage-deprecation-trial-enabled.https-expected.txt
new file mode 100644
index 0000000..dc99414
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-locks/storage-deprecation-trial-enabled.https-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 511, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 612, in do_testharness\n    done, rv = handler(result)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py", line 732, in __call__\n    url, command, payload = result\nTypeError: cannot unpack non-iterable NoneType object\n
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-arity.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-arity.https-expected.txt
new file mode 100644
index 0000000..aee631c8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-arity.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] extra ShareData field (extra field ignored)
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] 2 arguments (extra argument ignored)
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-error.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-error.https-expected.txt
new file mode 100644
index 0000000..7f3608e3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-error.https-expected.txt
@@ -0,0 +1,20 @@
+This is a testharness.js-based test.
+[FAIL] share with user cancellation
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] share with internal error
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] share with data url
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] share consumes user activation
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] only one share at a time
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] Failed file share does not lead to InvalidStateError
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] share with excessive title
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] share with excessive text
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] share with excessive url
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-nonutf8-encoding.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-nonutf8-encoding.https-expected.txt
new file mode 100644
index 0000000..571213eb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-nonutf8-encoding.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] successful share with Unicode characters
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-success.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-success.https-expected.txt
new file mode 100644
index 0000000..d35f3a9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-success.https-expected.txt
@@ -0,0 +1,18 @@
+This is a testharness.js-based test.
+[FAIL] successful share
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] successful share with URL without a scheme
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] successful share with a path-only URL
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] successful share with a relative URL
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] successful share with an empty URL
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] successful share with percent-encoded URL characters
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] successful share with Unicode characters
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] successful share with long strings
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-types.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-types.https-expected.txt
new file mode 100644
index 0000000..9557932
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-types.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+[FAIL] share of types other than string (expect implicitly converted to string)
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+[FAIL] share of null/undefined dict values
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-url-relative.https.sub-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-url-relative.https.sub-expected.txt
new file mode 100644
index 0000000..9f18b1de
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/web-share/share-url-relative.https.sub-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] successful share with a URL relative to document base URL
+  promise_test: Unhandled rejection with value: object "ReferenceError: eventSender is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webaudio/channel-count-detached-frame.window-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webaudio/channel-count-detached-frame.window-expected.txt
new file mode 100644
index 0000000..aa9ade0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webaudio/channel-count-detached-frame.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Changing channel after detaching the document throws an exception.
+  GCController is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/add-port.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/add-port.https-expected.txt
new file mode 100644
index 0000000..a2560ed
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/add-port.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test if newly connected ports work correctly
+  internals is not defined
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/open-close.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/open-close.https-expected.txt
new file mode 100644
index 0000000..ee09fb1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/open-close.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Cannot set properties of undefined (setting 'onstatechange')
+[PASS] opening and closing MIDI devices
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/permission.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/permission.https-expected.txt
new file mode 100644
index 0000000..533736a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/permission.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] sysex permission grants are properly handled
+  promise_test: Unhandled rejection with value: object "ReferenceError: internals is not defined"
+[PASS] sysex permission rejections are properly handled
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/requestmidiaccess.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/requestmidiaccess.https-expected.txt
new file mode 100644
index 0000000..e5af1c7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/requestmidiaccess.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: internals is not defined
+[PASS] basic MIDI access is functional
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/send-messages.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/send-messages.https-expected.txt
new file mode 100644
index 0000000..bd9fae9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/send-messages.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: internals is not defined
+[PASS] various MIDI messages can be validated
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/send-system-messages.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/send-system-messages.https-expected.txt
new file mode 100644
index 0000000..83e45a8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webmidi/send-system-messages.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: internals is not defined
+[PASS] various types of system messages can be validated
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/websocket-cookies/third-party-cookie-blocked-on-cross-origin-websocket.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/websocket-cookies/third-party-cookie-blocked-on-cross-origin-websocket.https-expected.txt
new file mode 100644
index 0000000..af7c4f2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/websocket-cookies/third-party-cookie-blocked-on-cross-origin-websocket.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test that first-party cookies are blocked for WebSockets conforming the requirements of the SameSite attribute.
+  assert_equals: expected "DONE: (none)" but got "DONE: samesite-none=value"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/websocket-cookies/third-party-cookie-blocked-on-same-origin-websocket.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/websocket-cookies/third-party-cookie-blocked-on-same-origin-websocket.https-expected.txt
new file mode 100644
index 0000000..30fd096
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/websocket-cookies/third-party-cookie-blocked-on-same-origin-websocket.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test that third-party cookies are blocked for WebSockets even when the WebSocket's URL's domain is an exact match for the domain of its initiator.
+  assert_equals: expected "DONE: (none)" but got "DONE: samesite-none=value"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-enabled-local.sub.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-enabled-local.sub.https-expected.txt
new file mode 100644
index 0000000..56d01937d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-enabled-local.sub.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test for Local Storage with DisableThirdPartySessionStoragePartitioning enabled
+  assert_true: IDs pulled from same-origin un-partitioned frames shouldn't be different. expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-enabled-session.sub.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-enabled-session.sub.https-expected.txt
new file mode 100644
index 0000000..2f1afa31
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-enabled-session.sub.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test for Session Storage with DisableThirdPartySessionStoragePartitioning enabled
+  assert_true: IDs pulled from same-origin un-partitioned frames shouldn't be different. expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-third-party-enabled-local.sub.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-third-party-enabled-local.sub.https-expected.txt
new file mode 100644
index 0000000..8b3c120d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-third-party-enabled-local.sub.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test for Local Storage with DisableThirdPartySessionStoragePartitioning enabled in cross-origin iframe
+  assert_true: IDs pulled from same-origin un-partitioned frames shouldn't be different. expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-third-party-enabled-session.sub.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-third-party-enabled-session.sub.https-expected.txt
new file mode 100644
index 0000000..a3f68bc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/general-storage-deprecation-trial-third-party-enabled-session.sub.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test for Session Storage with DisableThirdPartySessionStoragePartitioning enabled in cross-origin iframe
+  assert_true: IDs pulled from same-origin un-partitioned frames shouldn't be different. expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/storage-deprecation-trial-enabled-session.sub.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/storage-deprecation-trial-enabled-session.sub.https-expected.txt
new file mode 100644
index 0000000..d3e8752
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/storage-deprecation-trial-enabled-session.sub.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test for Session Storage with DisableThirdPartySessionStoragePartitioningAfterGeneralPartitioning enabled
+  assert_true: IDs pulled from same-origin un-partitioned frames shouldn't be different. expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/storage-deprecation-trial-redirect-session.sub.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/storage-deprecation-trial-redirect-session.sub.https-expected.txt
new file mode 100644
index 0000000..242a084
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webstorage/storage-deprecation-trial-redirect-session.sub.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Test for Session Storage with DisableThirdPartySessionStoragePartitioningAfterGeneralPartitioning enabled and a cross-origin redirect
+  assert_true: The session storage data must be consistent. expected true got false
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webtransport/subresource-filter-disallowed.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webtransport/subresource-filter-disallowed.https-expected.txt
new file mode 100644
index 0000000..98c30162
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webtransport/subresource-filter-disallowed.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[PASS] WebTransport session is established with status code 200
+[FAIL] Request suffixed with "headers.py" should be blocked.
+  assert_unreached: Should have rejected: undefined Reached unreachable code
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webusb/usb-iframe.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webusb/usb-iframe.https-expected.txt
new file mode 100644
index 0000000..b03741a4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webusb/usb-iframe.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] detaching from iframe invalidates reference to the iframe USB object
+  promise_test: Unhandled rejection with value: object "ReferenceError: GCController is not defined"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webusb/usbDevice-iframe.https-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webusb/usbDevice-iframe.https-expected.txt
new file mode 100644
index 0000000..94dbb2e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux-chrome/wpt_internal/webusb/usbDevice-iframe.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Uncaught ReferenceError: GCController is not defined
+[TIMEOUT] events are not delivered to detached frames
+  Test timed out
+[NOTRUN] forget() rejects in a detached context
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/fledge-rounding/README.md b/third_party/blink/web_tests/virtual/fledge-rounding/README.md
index 569e7d7..3f0784f 100644
--- a/third_party/blink/web_tests/virtual/fledge-rounding/README.md
+++ b/third_party/blink/web_tests/virtual/fledge-rounding/README.md
@@ -1,3 +1,6 @@
-This directory is for running tests with FLEDGE
-(https://github.com/WICG/turtledove/blob/main/FLEDGE.md) on.
+This directory is to test rounding values feature for Protected Audience with FLEDGE (https://github.com/WICG/turtledove/blob/main/FLEDGE.md) on.
 
+The rounding value feature is governed by the `FledgeRounding` flag and consists of three distinct detailed configurations:
+* `fledge_bid_reporting_bits`: `browserSignals.bid` of `generateBid()`
+* `fledge_score_reporting_bits`: `browserSignals.desirability`, `browserSignals.highestScoringOtherBid` of `scoreAd()`
+* `fledge_ad_cost_reporting_bits`: `browserSignals.adCost` of `generateBid()`
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/location-change-repeated-from-blank-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/location-change-repeated-from-blank-expected.txt
deleted file mode 100644
index 4dec770..0000000
--- a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/location-change-repeated-from-blank-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-This test checks the following case:
-* Create an iframe
-* Set its location to about:blank
-* In a setTimeout(), navigate to a non-blank page
-The iframe navigations should not create new history entries, even though the non-blank navigation is after the load (there is only one history entry in the iframe context, and it is about:blank). 
-
-============== Back Forward List ==============
-curr->  http://127.0.0.1:8000/navigation/location-change-repeated-from-blank.html
-            http://127.0.0.1:8000/navigation/resources/pass-and-notify-done.html (in frame "i")
-===============================================
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 871e41a..aace6872 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
@@ -5248,7 +5248,6 @@
     method constructor
     method getFrequencyResponse
 interface IdentityCredential : Credential
-    static method logoutRPs
     static method revoke
     attribute @@toStringTag
     getter isAutoSelected
diff --git a/third_party/blink/web_tests/wpt_internal/mediastream/frame-reader-worker.js b/third_party/blink/web_tests/wpt_internal/mediastream/frame-reader-worker.js
index f2e4540f..0b29fd40 100644
--- a/third_party/blink/web_tests/wpt_internal/mediastream/frame-reader-worker.js
+++ b/third_party/blink/web_tests/wpt_internal/mediastream/frame-reader-worker.js
@@ -6,7 +6,7 @@
   const frameStream = e.data.stream;
   const frameReader = frameStream.getReader();
 
-  const framesToRead = 20;
+  const framesToRead = 10;
 
   var closeStream = function() {
     frameReader.releaseLock();
diff --git a/third_party/blink/web_tests/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker.html b/third_party/blink/web_tests/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker.html
index e51eb53..17103343 100644
--- a/third_party/blink/web_tests/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker.html
+++ b/third_party/blink/web_tests/wpt_internal/mediastream/mediastreamtrackprocessor-transfer-to-worker.html
@@ -25,7 +25,7 @@
 
 promise_test(async t => {
   var video = document.createElement('video');
-  video.src = "/media/400x300-red-resize-200x150-green.mp4";
+  video.src = "/media/movie_5.mp4";
   await test_driver.bless("Play video element", () => {
     return video.play();
   });
diff --git a/third_party/catapult b/third_party/catapult
index 448b931..c6db8519 160000
--- a/third_party/catapult
+++ b/third_party/catapult
@@ -1 +1 @@
-Subproject commit 448b931d9af81cee1f1bcf89672ccbad21a2513e
+Subproject commit c6db8519c02ae6a5afac0358c266dc3e5f2fd803
diff --git a/third_party/chromite b/third_party/chromite
index c59189f..e2b86e4 160000
--- a/third_party/chromite
+++ b/third_party/chromite
@@ -1 +1 @@
-Subproject commit c59189f1626e3a47873dfd17835da8c749c74a33
+Subproject commit e2b86e44a8f0dda3b5ef536950ebf2c0d2021680
diff --git a/third_party/closure_compiler/externs/input_method_private.js b/third_party/closure_compiler/externs/input_method_private.js
index 6be97e3..851524e 100644
--- a/third_party/closure_compiler/externs/input_method_private.js
+++ b/third_party/closure_compiler/externs/input_method_private.js
@@ -428,13 +428,6 @@
 chrome.inputMethodPrivate.onFocus;
 
 /**
- * This event is sent when a touch occurs in a text field. Should only happen
- * after onFocus()
- * @type {!ChromeEvent}
- */
-chrome.inputMethodPrivate.onTouch;
-
-/**
  * This event is sent when the settings for any input method changed. It is sent
  * to all extensions that are listening to this event, and enabled by the user.
  * @type {!ChromeEvent}
diff --git a/third_party/closure_compiler/externs/pending.js b/third_party/closure_compiler/externs/pending.js
index 996b7582..a55969a8 100644
--- a/third_party/closure_compiler/externs/pending.js
+++ b/third_party/closure_compiler/externs/pending.js
@@ -66,3 +66,11 @@
 
 /** @return {!Array<!Object>} */
 AnimationEffect.prototype.getKeyframes = function() {};
+
+/**
+ * https://developer.mozilla.org/en-US/docs/Web/API/structuredClone
+ * @param {T} obj
+ * @return {T}
+ * @template T
+ */
+function structuredClone(obj) {}
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium
index 22251cb..fff83d6 100644
--- a/third_party/crashpad/README.chromium
+++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@
 Short Name: crashpad
 URL: https://crashpad.chromium.org/
 Version: N/A
-Revision: 3ba2403a73927815627fde482d19dfb3454a7a5f
+Revision: 1675ce7c586c2a3ad3a03dd82e983fd6c188c7fc
 License: Apache 2.0
 License File: crashpad/LICENSE
 Security Critical: yes
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS
index 909ef7d..aad7bbc 100644
--- a/third_party/crashpad/crashpad/DEPS
+++ b/third_party/crashpad/crashpad/DEPS
@@ -47,7 +47,7 @@
       '9719c1e1e676814c456b55f5f070eabad6709d31',
   'crashpad/third_party/mini_chromium/mini_chromium':
       Var('chromium_git') + '/chromium/mini_chromium@' +
-      '98bbdbe49f4ac26318f88aa7e84296a3da22f7d8',
+      'e508a6010e25ba2619317b45995a30f65d2af9b3',
   'crashpad/third_party/libfuzzer/src':
       Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' +
       'fda403cf93ecb8792cb1d061564d89a6553ca020',
diff --git a/third_party/crashpad/crashpad/client/pthread_create_linux.cc b/third_party/crashpad/crashpad/client/pthread_create_linux.cc
index acbf57d..86ff8dba 100644
--- a/third_party/crashpad/crashpad/client/pthread_create_linux.cc
+++ b/third_party/crashpad/crashpad/client/pthread_create_linux.cc
@@ -15,6 +15,7 @@
 #include <dlfcn.h>
 #include <pthread.h>
 
+#include "base/check.h"
 #include "base/logging.h"
 #include "client/crashpad_client.h"
 #include "util/misc/no_cfi_icall.h"
diff --git a/third_party/crashpad/crashpad/handler/mac/exception_handler_server.cc b/third_party/crashpad/crashpad/handler/mac/exception_handler_server.cc
index 5357c8c..5c1814c8 100644
--- a/third_party/crashpad/crashpad/handler/mac/exception_handler_server.cc
+++ b/third_party/crashpad/crashpad/handler/mac/exception_handler_server.cc
@@ -17,6 +17,7 @@
 #include <utility>
 
 #include "base/apple/mach_logging.h"
+#include "base/check.h"
 #include "base/logging.h"
 #include "util/mach/composite_mach_message_server.h"
 #include "util/mach/mach_extensions.h"
diff --git a/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc b/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc
index 658a225..0929f33 100644
--- a/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc
+++ b/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc
@@ -25,6 +25,7 @@
 #include <type_traits>
 #include <vector>
 
+#include "base/check.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "build/build_config.h"
diff --git a/third_party/crashpad/crashpad/handler/win/fastfail_test_program.cc b/third_party/crashpad/crashpad/handler/win/fastfail_test_program.cc
index 346aa68a..f654119 100644
--- a/third_party/crashpad/crashpad/handler/win/fastfail_test_program.cc
+++ b/third_party/crashpad/crashpad/handler/win/fastfail_test_program.cc
@@ -14,6 +14,7 @@
 
 #include <string.h>
 
+#include "base/check.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "client/crashpad_client.h"
diff --git a/third_party/crashpad/crashpad/handler/win/hanging_program.cc b/third_party/crashpad/crashpad/handler/win/hanging_program.cc
index 2404bf30..72f903f 100644
--- a/third_party/crashpad/crashpad/handler/win/hanging_program.cc
+++ b/third_party/crashpad/crashpad/handler/win/hanging_program.cc
@@ -17,6 +17,7 @@
 
 #include <iterator>
 
+#include "base/check.h"
 #include "base/debug/alias.h"
 #include "base/logging.h"
 #include "base/notreached.h"
diff --git a/third_party/crashpad/crashpad/handler/win/heap_corrupting_program.cc b/third_party/crashpad/crashpad/handler/win/heap_corrupting_program.cc
index 6c7c2cd..8fe62f6 100644
--- a/third_party/crashpad/crashpad/handler/win/heap_corrupting_program.cc
+++ b/third_party/crashpad/crashpad/handler/win/heap_corrupting_program.cc
@@ -14,6 +14,7 @@
 
 #include <string.h>
 
+#include "base/check.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "client/crashpad_client.h"
diff --git a/third_party/crashpad/crashpad/test/test_paths.cc b/third_party/crashpad/crashpad/test/test_paths.cc
index 1e1c250a..75399ac 100644
--- a/third_party/crashpad/crashpad/test/test_paths.cc
+++ b/third_party/crashpad/crashpad/test/test_paths.cc
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 
+#include "base/check.h"
 #include "base/logging.h"
 #include "build/build_config.h"
 #include "util/misc/paths.h"
diff --git a/third_party/crashpad/crashpad/test/win/win_child_process.cc b/third_party/crashpad/crashpad/test/win/win_child_process.cc
index d1a767c..d4d9a46 100644
--- a/third_party/crashpad/crashpad/test/win/win_child_process.cc
+++ b/third_party/crashpad/crashpad/test/win/win_child_process.cc
@@ -20,6 +20,7 @@
 #include <string>
 #include <utility>
 
+#include "base/check.h"
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/third_party/crashpad/crashpad/util/file/directory_reader_posix.cc b/third_party/crashpad/crashpad/util/file/directory_reader_posix.cc
index d046eb11..352991d 100644
--- a/third_party/crashpad/crashpad/util/file/directory_reader_posix.cc
+++ b/third_party/crashpad/crashpad/util/file/directory_reader_posix.cc
@@ -19,6 +19,7 @@
 #include <string.h>
 #include <sys/types.h>
 
+#include "base/check.h"
 #include "base/logging.h"
 
 namespace crashpad {
diff --git a/third_party/crashpad/crashpad/util/file/directory_reader_win.cc b/third_party/crashpad/crashpad/util/file/directory_reader_win.cc
index e1bb38e..95251183 100644
--- a/third_party/crashpad/crashpad/util/file/directory_reader_win.cc
+++ b/third_party/crashpad/crashpad/util/file/directory_reader_win.cc
@@ -16,6 +16,7 @@
 
 #include <string.h>
 
+#include "base/check.h"
 #include "base/logging.h"
 
 namespace crashpad {
diff --git a/third_party/crashpad/crashpad/util/posix/process_info_linux.cc b/third_party/crashpad/crashpad/util/posix/process_info_linux.cc
index 27387616..1aca699c 100644
--- a/third_party/crashpad/crashpad/util/posix/process_info_linux.cc
+++ b/third_party/crashpad/crashpad/util/posix/process_info_linux.cc
@@ -16,6 +16,7 @@
 
 #include <stdio.h>
 
+#include "base/check.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "util/file/delimited_file_reader.h"
diff --git a/third_party/crashpad/crashpad/util/stream/file_output_stream.cc b/third_party/crashpad/crashpad/util/stream/file_output_stream.cc
index 91aed904..a3633f9 100644
--- a/third_party/crashpad/crashpad/util/stream/file_output_stream.cc
+++ b/third_party/crashpad/crashpad/util/stream/file_output_stream.cc
@@ -14,6 +14,7 @@
 
 #include "util/stream/file_output_stream.h"
 
+#include "base/check.h"
 #include "base/logging.h"
 
 namespace crashpad {
diff --git a/third_party/crashpad/crashpad/util/win/exception_handler_server.cc b/third_party/crashpad/crashpad/util/win/exception_handler_server.cc
index ba938ec9..e641c7fb 100644
--- a/third_party/crashpad/crashpad/util/win/exception_handler_server.cc
+++ b/third_party/crashpad/crashpad/util/win/exception_handler_server.cc
@@ -21,6 +21,7 @@
 #include <iterator>
 #include <utility>
 
+#include "base/check.h"
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/rand_util.h"
diff --git a/third_party/crashpad/crashpad/util/win/registration_protocol_win.cc b/third_party/crashpad/crashpad/util/win/registration_protocol_win.cc
index e729f5d..59a7bbd 100644
--- a/third_party/crashpad/crashpad/util/win/registration_protocol_win.cc
+++ b/third_party/crashpad/crashpad/util/win/registration_protocol_win.cc
@@ -25,6 +25,7 @@
 
 #include <iterator>
 
+#include "base/check.h"
 #include "base/logging.h"
 #include "util/win/exception_handler_server.h"
 #include "util/win/loader_lock.h"
diff --git a/third_party/crashpad/crashpad/util/win/session_end_watcher.cc b/third_party/crashpad/crashpad/util/win/session_end_watcher.cc
index d685a995f..ead6b7fc 100644
--- a/third_party/crashpad/crashpad/util/win/session_end_watcher.cc
+++ b/third_party/crashpad/crashpad/util/win/session_end_watcher.cc
@@ -14,6 +14,7 @@
 
 #include "util/win/session_end_watcher.h"
 
+#include "base/check.h"
 #include "base/logging.h"
 #include "base/scoped_generic.h"
 #include "util/win/scoped_set_event.h"
diff --git a/third_party/cros_system_api b/third_party/cros_system_api
index d82c199..bfe3cc4 160000
--- a/third_party/cros_system_api
+++ b/third_party/cros_system_api
@@ -1 +1 @@
-Subproject commit d82c19922e3cc3eb5693a8dda094e8c509de5c0b
+Subproject commit bfe3cc4e3041356c1d0fd615ab232ca7199a0d59
diff --git a/third_party/dawn b/third_party/dawn
index 3ec3339..e2cd8aa 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit 3ec333906a355a569954ce4822852cda98dd7f23
+Subproject commit e2cd8aade99ffd2d2b97fe87fd43b08f22002692
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal
index 30f443d..2c4d976 160000
--- a/third_party/devtools-frontend-internal
+++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@
-Subproject commit 30f443dc48bf5d1f37db4de38781a6e46e41169c
+Subproject commit 2c4d976019118bab0f3e12634570728fcb658494
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index 53b8fca4..1088b03 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit 53b8fca44fd4432af2d1f671d2a7f231fe8038a4
+Subproject commit 1088b0366ce6feff0dab1f8ef102a6d2ee801ed3
diff --git a/third_party/expat/BUILD.gn b/third_party/expat/BUILD.gn
index 7699d1c..6d11f36 100644
--- a/third_party/expat/BUILD.gn
+++ b/third_party/expat/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 
 # On Linux, we implicitly already depend on expat via fontconfig;
diff --git a/third_party/freetype/BUILD.gn b/third_party/freetype/BUILD.gn
index 903d266..d2318036 100644
--- a/third_party/freetype/BUILD.gn
+++ b/third_party/freetype/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/freetype/freetype.gni")
 import("//third_party/harfbuzz-ng/harfbuzz.gni")
 
diff --git a/third_party/leveldatabase/env_chromium.cc b/third_party/leveldatabase/env_chromium.cc
index da0c613..4e047ee1 100644
--- a/third_party/leveldatabase/env_chromium.cc
+++ b/third_party/leveldatabase/env_chromium.cc
@@ -73,6 +73,11 @@
 // able to recover data.
 static const char kDatabaseNameSuffixForRebuildDB[] = "__tmp_for_rebuild";
 
+DBFactoryMethod& GetDBFactoryOverride() {
+  static base::NoDestructor<DBFactoryMethod> instance;
+  return *instance;
+}
+
 class ChromiumFileLock : public FileLock {
  public:
   ChromiumFileLock(std::unique_ptr<storage::FilesystemProxy::FileLock> lock,
@@ -1369,6 +1374,10 @@
 leveldb::Status OpenDB(const leveldb_env::Options& options,
                        const std::string& name,
                        std::unique_ptr<leveldb::DB>* dbptr) {
+  if (!GetDBFactoryOverride().is_null()) {
+    return GetDBFactoryOverride().Run(options, name, dbptr);
+  }
+
   // For UMA logging purposes we need the block cache to be created outside of
   // leveldb so that the size can be logged and it can be pruned.
   DCHECK(options.block_cache != nullptr);
@@ -1414,6 +1423,10 @@
   return s;
 }
 
+void SetDBFactoryForTesting(DBFactoryMethod factory) {
+  GetDBFactoryOverride() = factory;
+}
+
 leveldb::Status RewriteDB(const leveldb_env::Options& options,
                           const std::string& name,
                           std::unique_ptr<leveldb::DB>* dbptr) {
diff --git a/third_party/leveldatabase/env_chromium.h b/third_party/leveldatabase/env_chromium.h
index 0b29dcc17..aa5c604 100644
--- a/third_party/leveldatabase/env_chromium.h
+++ b/third_party/leveldatabase/env_chromium.h
@@ -305,6 +305,13 @@
                                       const std::string& name,
                                       std::unique_ptr<leveldb::DB>* dbptr);
 
+// Overrides OpenDB with the given closure.
+using DBFactoryMethod =
+    base::RepeatingCallback<leveldb::Status(const leveldb_env::Options&,
+                                            const std::string&,
+                                            std::unique_ptr<leveldb::DB>*)>;
+LEVELDB_EXPORT void SetDBFactoryForTesting(DBFactoryMethod factory);
+
 // Copies the content of |dbptr| into a fresh database to remove traces of
 // deleted data. |options| and |name| of the old database are required to create
 // an identical copy. |dbptr| will be replaced with the new database on success.
diff --git a/third_party/libaom/README.chromium b/third_party/libaom/README.chromium
index d5e606fd..9b826e93 100644
--- a/third_party/libaom/README.chromium
+++ b/third_party/libaom/README.chromium
@@ -2,7 +2,7 @@
 Short Name: libaom
 URL: https://aomedia.googlesource.com/aom/
 Version: N/A
-Revision: 1dbe1c7fae2456f91ccc79fecb919e9ffea0727a
+Revision: 7b5f665231dfbcc5abc49d3b8d6d8826c75ce473
 CPEPrefix: cpe:/a:aomedia:aomedia:3.6.1
 License: BSD
 License File: source/libaom/LICENSE
diff --git a/third_party/libaom/libaom_srcs.gni b/third_party/libaom/libaom_srcs.gni
index 48f572e..dbf9b6f 100644
--- a/third_party/libaom/libaom_srcs.gni
+++ b/third_party/libaom/libaom_srcs.gni
@@ -214,6 +214,7 @@
   "//third_party/libaom/source/libaom/av1/encoder/arm/neon/av1_highbd_quantize_neon.c",
   "//third_party/libaom/source/libaom/av1/encoder/arm/neon/ml_neon.c",
   "//third_party/libaom/source/libaom/av1/encoder/arm/neon/pickrst_neon.c",
+  "//third_party/libaom/source/libaom/av1/encoder/arm/neon/pickrst_neon.h",
   "//third_party/libaom/source/libaom/av1/encoder/arm/neon/rdopt_neon.c",
   "//third_party/libaom/source/libaom/av1/encoder/arm/neon/av1_error_neon.c",
   "//third_party/libaom/source/libaom/av1/encoder/arm/neon/encodetxb_neon.c",
diff --git a/third_party/libaom/options.gni b/third_party/libaom/options.gni
index 40db01b..e54e6f0f 100644
--- a/third_party/libaom/options.gni
+++ b/third_party/libaom/options.gni
@@ -1,4 +1,4 @@
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/gclient_args.gni")
 
diff --git a/third_party/libaom/source/config/config/aom_version.h b/third_party/libaom/source/config/config/aom_version.h
index 8d45ae63..77d0fed 100644
--- a/third_party/libaom/source/config/config/aom_version.h
+++ b/third_party/libaom/source/config/config/aom_version.h
@@ -12,8 +12,8 @@
 #define VERSION_MAJOR 3
 #define VERSION_MINOR 7
 #define VERSION_PATCH 0
-#define VERSION_EXTRA "593-g1dbe1c7fae"
+#define VERSION_EXTRA "624-g7b5f665231"
 #define VERSION_PACKED \
   ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH))
-#define VERSION_STRING_NOSP "3.7.0-593-g1dbe1c7fae"
-#define VERSION_STRING " 3.7.0-593-g1dbe1c7fae"
+#define VERSION_STRING_NOSP "3.7.0-624-g7b5f665231"
+#define VERSION_STRING " 3.7.0-624-g7b5f665231"
diff --git a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h
index 652e6e3..77a3bc4a 100644
--- a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h
@@ -703,9 +703,40 @@
 uint64_t av1_wedge_sse_from_residuals_neon(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 RTCD_EXTERN uint64_t (*av1_wedge_sse_from_residuals)(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 
-void av1_wiener_convolve_add_src_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-void av1_wiener_convolve_add_src_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-RTCD_EXTERN void (*av1_wiener_convolve_add_src)(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
+void av1_wiener_convolve_add_src_c(const uint8_t* src,
+                                   ptrdiff_t src_stride,
+                                   uint8_t* dst,
+                                   ptrdiff_t dst_stride,
+                                   const int16_t* filter_x,
+                                   int x_step_q4,
+                                   const int16_t* filter_y,
+                                   int y_step_q4,
+                                   int w,
+                                   int h,
+                                   const WienerConvolveParams* conv_params);
+void av1_wiener_convolve_add_src_neon(const uint8_t* src,
+                                      ptrdiff_t src_stride,
+                                      uint8_t* dst,
+                                      ptrdiff_t dst_stride,
+                                      const int16_t* filter_x,
+                                      int x_step_q4,
+                                      const int16_t* filter_y,
+                                      int y_step_q4,
+                                      int w,
+                                      int h,
+                                      const WienerConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_wiener_convolve_add_src)(
+    const uint8_t* src,
+    ptrdiff_t src_stride,
+    uint8_t* dst,
+    ptrdiff_t dst_stride,
+    const int16_t* filter_x,
+    int x_step_q4,
+    const int16_t* filter_y,
+    int y_step_q4,
+    int w,
+    int h,
+    const WienerConvolveParams* conv_params);
 
 void cdef_copy_rect8_16bit_to_16bit_c(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
 void cdef_copy_rect8_16bit_to_16bit_neon(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
diff --git a/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h
index b9f1c71a..0fd8c9d8 100644
--- a/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h
@@ -610,8 +610,28 @@
 uint64_t av1_wedge_sse_from_residuals_neon(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 #define av1_wedge_sse_from_residuals av1_wedge_sse_from_residuals_neon
 
-void av1_wiener_convolve_add_src_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-void av1_wiener_convolve_add_src_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
+void av1_wiener_convolve_add_src_c(const uint8_t* src,
+                                   ptrdiff_t src_stride,
+                                   uint8_t* dst,
+                                   ptrdiff_t dst_stride,
+                                   const int16_t* filter_x,
+                                   int x_step_q4,
+                                   const int16_t* filter_y,
+                                   int y_step_q4,
+                                   int w,
+                                   int h,
+                                   const WienerConvolveParams* conv_params);
+void av1_wiener_convolve_add_src_neon(const uint8_t* src,
+                                      ptrdiff_t src_stride,
+                                      uint8_t* dst,
+                                      ptrdiff_t dst_stride,
+                                      const int16_t* filter_x,
+                                      int x_step_q4,
+                                      const int16_t* filter_y,
+                                      int y_step_q4,
+                                      int w,
+                                      int h,
+                                      const WienerConvolveParams* conv_params);
 #define av1_wiener_convolve_add_src av1_wiener_convolve_add_src_neon
 
 void cdef_copy_rect8_16bit_to_16bit_c(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
diff --git a/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h
index 719b526..ac766c2 100644
--- a/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h
@@ -426,7 +426,17 @@
 uint64_t av1_wedge_sse_from_residuals_c(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 #define av1_wedge_sse_from_residuals av1_wedge_sse_from_residuals_c
 
-void av1_wiener_convolve_add_src_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
+void av1_wiener_convolve_add_src_c(const uint8_t* src,
+                                   ptrdiff_t src_stride,
+                                   uint8_t* dst,
+                                   ptrdiff_t dst_stride,
+                                   const int16_t* filter_x,
+                                   int x_step_q4,
+                                   const int16_t* filter_y,
+                                   int y_step_q4,
+                                   int w,
+                                   int h,
+                                   const WienerConvolveParams* conv_params);
 #define av1_wiener_convolve_add_src av1_wiener_convolve_add_src_c
 
 void cdef_copy_rect8_16bit_to_16bit_c(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
diff --git a/third_party/libaom/source/config/linux/arm64-cpu-detect/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm64-cpu-detect/config/av1_rtcd.h
index 3cb2c5a..be2822f 100644
--- a/third_party/libaom/source/config/linux/arm64-cpu-detect/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm64-cpu-detect/config/av1_rtcd.h
@@ -1705,7 +1705,7 @@
                                    int y_step_q4,
                                    int w,
                                    int h,
-                                   const ConvolveParams* conv_params);
+                                   const WienerConvolveParams* conv_params);
 void av1_wiener_convolve_add_src_neon(const uint8_t* src,
                                       ptrdiff_t src_stride,
                                       uint8_t* dst,
@@ -1716,7 +1716,7 @@
                                       int y_step_q4,
                                       int w,
                                       int h,
-                                      const ConvolveParams* conv_params);
+                                      const WienerConvolveParams* conv_params);
 #define av1_wiener_convolve_add_src av1_wiener_convolve_add_src_neon
 
 void cdef_copy_rect8_16bit_to_16bit_c(uint16_t* dst,
diff --git a/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h b/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h
index 4418b7d1..8ea384e 100644
--- a/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h
@@ -426,7 +426,17 @@
 uint64_t av1_wedge_sse_from_residuals_c(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 #define av1_wedge_sse_from_residuals av1_wedge_sse_from_residuals_c
 
-void av1_wiener_convolve_add_src_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
+void av1_wiener_convolve_add_src_c(const uint8_t* src,
+                                   ptrdiff_t src_stride,
+                                   uint8_t* dst,
+                                   ptrdiff_t dst_stride,
+                                   const int16_t* filter_x,
+                                   int x_step_q4,
+                                   const int16_t* filter_y,
+                                   int y_step_q4,
+                                   int w,
+                                   int h,
+                                   const WienerConvolveParams* conv_params);
 #define av1_wiener_convolve_add_src av1_wiener_convolve_add_src_c
 
 void cdef_copy_rect8_16bit_to_16bit_c(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
diff --git a/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h b/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h
index efc39dae..0c01a89c 100644
--- a/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h
@@ -554,10 +554,51 @@
 uint64_t av1_wedge_sse_from_residuals_avx2(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 RTCD_EXTERN uint64_t (*av1_wedge_sse_from_residuals)(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 
-void av1_wiener_convolve_add_src_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-void av1_wiener_convolve_add_src_sse2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-void av1_wiener_convolve_add_src_avx2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-RTCD_EXTERN void (*av1_wiener_convolve_add_src)(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
+void av1_wiener_convolve_add_src_c(const uint8_t* src,
+                                   ptrdiff_t src_stride,
+                                   uint8_t* dst,
+                                   ptrdiff_t dst_stride,
+                                   const int16_t* filter_x,
+                                   int x_step_q4,
+                                   const int16_t* filter_y,
+                                   int y_step_q4,
+                                   int w,
+                                   int h,
+                                   const WienerConvolveParams* conv_params);
+void av1_wiener_convolve_add_src_sse2(const uint8_t* src,
+                                      ptrdiff_t src_stride,
+                                      uint8_t* dst,
+                                      ptrdiff_t dst_stride,
+                                      const int16_t* filter_x,
+                                      int x_step_q4,
+                                      const int16_t* filter_y,
+                                      int y_step_q4,
+                                      int w,
+                                      int h,
+                                      const WienerConvolveParams* conv_params);
+void av1_wiener_convolve_add_src_avx2(const uint8_t* src,
+                                      ptrdiff_t src_stride,
+                                      uint8_t* dst,
+                                      ptrdiff_t dst_stride,
+                                      const int16_t* filter_x,
+                                      int x_step_q4,
+                                      const int16_t* filter_y,
+                                      int y_step_q4,
+                                      int w,
+                                      int h,
+                                      const WienerConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_wiener_convolve_add_src)(
+    const uint8_t* src,
+    ptrdiff_t src_stride,
+    uint8_t* dst,
+    ptrdiff_t dst_stride,
+    const int16_t* filter_x,
+    int x_step_q4,
+    const int16_t* filter_y,
+    int y_step_q4,
+    int w,
+    int h,
+    const WienerConvolveParams* conv_params);
 
 void cdef_copy_rect8_16bit_to_16bit_c(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
 void cdef_copy_rect8_16bit_to_16bit_sse2(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
diff --git a/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h b/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h
index efc39dae..0c01a89c 100644
--- a/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h
@@ -554,10 +554,51 @@
 uint64_t av1_wedge_sse_from_residuals_avx2(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 RTCD_EXTERN uint64_t (*av1_wedge_sse_from_residuals)(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 
-void av1_wiener_convolve_add_src_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-void av1_wiener_convolve_add_src_sse2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-void av1_wiener_convolve_add_src_avx2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-RTCD_EXTERN void (*av1_wiener_convolve_add_src)(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
+void av1_wiener_convolve_add_src_c(const uint8_t* src,
+                                   ptrdiff_t src_stride,
+                                   uint8_t* dst,
+                                   ptrdiff_t dst_stride,
+                                   const int16_t* filter_x,
+                                   int x_step_q4,
+                                   const int16_t* filter_y,
+                                   int y_step_q4,
+                                   int w,
+                                   int h,
+                                   const WienerConvolveParams* conv_params);
+void av1_wiener_convolve_add_src_sse2(const uint8_t* src,
+                                      ptrdiff_t src_stride,
+                                      uint8_t* dst,
+                                      ptrdiff_t dst_stride,
+                                      const int16_t* filter_x,
+                                      int x_step_q4,
+                                      const int16_t* filter_y,
+                                      int y_step_q4,
+                                      int w,
+                                      int h,
+                                      const WienerConvolveParams* conv_params);
+void av1_wiener_convolve_add_src_avx2(const uint8_t* src,
+                                      ptrdiff_t src_stride,
+                                      uint8_t* dst,
+                                      ptrdiff_t dst_stride,
+                                      const int16_t* filter_x,
+                                      int x_step_q4,
+                                      const int16_t* filter_y,
+                                      int y_step_q4,
+                                      int w,
+                                      int h,
+                                      const WienerConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_wiener_convolve_add_src)(
+    const uint8_t* src,
+    ptrdiff_t src_stride,
+    uint8_t* dst,
+    ptrdiff_t dst_stride,
+    const int16_t* filter_x,
+    int x_step_q4,
+    const int16_t* filter_y,
+    int y_step_q4,
+    int w,
+    int h,
+    const WienerConvolveParams* conv_params);
 
 void cdef_copy_rect8_16bit_to_16bit_c(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
 void cdef_copy_rect8_16bit_to_16bit_sse2(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
diff --git a/third_party/libaom/source/config/win/arm64-cpu-detect/config/av1_rtcd.h b/third_party/libaom/source/config/win/arm64-cpu-detect/config/av1_rtcd.h
index 3cb2c5a..be2822f 100644
--- a/third_party/libaom/source/config/win/arm64-cpu-detect/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/win/arm64-cpu-detect/config/av1_rtcd.h
@@ -1705,7 +1705,7 @@
                                    int y_step_q4,
                                    int w,
                                    int h,
-                                   const ConvolveParams* conv_params);
+                                   const WienerConvolveParams* conv_params);
 void av1_wiener_convolve_add_src_neon(const uint8_t* src,
                                       ptrdiff_t src_stride,
                                       uint8_t* dst,
@@ -1716,7 +1716,7 @@
                                       int y_step_q4,
                                       int w,
                                       int h,
-                                      const ConvolveParams* conv_params);
+                                      const WienerConvolveParams* conv_params);
 #define av1_wiener_convolve_add_src av1_wiener_convolve_add_src_neon
 
 void cdef_copy_rect8_16bit_to_16bit_c(uint16_t* dst,
diff --git a/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h b/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h
index efc39dae..0c01a89c 100644
--- a/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h
@@ -554,10 +554,51 @@
 uint64_t av1_wedge_sse_from_residuals_avx2(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 RTCD_EXTERN uint64_t (*av1_wedge_sse_from_residuals)(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 
-void av1_wiener_convolve_add_src_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-void av1_wiener_convolve_add_src_sse2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-void av1_wiener_convolve_add_src_avx2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-RTCD_EXTERN void (*av1_wiener_convolve_add_src)(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
+void av1_wiener_convolve_add_src_c(const uint8_t* src,
+                                   ptrdiff_t src_stride,
+                                   uint8_t* dst,
+                                   ptrdiff_t dst_stride,
+                                   const int16_t* filter_x,
+                                   int x_step_q4,
+                                   const int16_t* filter_y,
+                                   int y_step_q4,
+                                   int w,
+                                   int h,
+                                   const WienerConvolveParams* conv_params);
+void av1_wiener_convolve_add_src_sse2(const uint8_t* src,
+                                      ptrdiff_t src_stride,
+                                      uint8_t* dst,
+                                      ptrdiff_t dst_stride,
+                                      const int16_t* filter_x,
+                                      int x_step_q4,
+                                      const int16_t* filter_y,
+                                      int y_step_q4,
+                                      int w,
+                                      int h,
+                                      const WienerConvolveParams* conv_params);
+void av1_wiener_convolve_add_src_avx2(const uint8_t* src,
+                                      ptrdiff_t src_stride,
+                                      uint8_t* dst,
+                                      ptrdiff_t dst_stride,
+                                      const int16_t* filter_x,
+                                      int x_step_q4,
+                                      const int16_t* filter_y,
+                                      int y_step_q4,
+                                      int w,
+                                      int h,
+                                      const WienerConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_wiener_convolve_add_src)(
+    const uint8_t* src,
+    ptrdiff_t src_stride,
+    uint8_t* dst,
+    ptrdiff_t dst_stride,
+    const int16_t* filter_x,
+    int x_step_q4,
+    const int16_t* filter_y,
+    int y_step_q4,
+    int w,
+    int h,
+    const WienerConvolveParams* conv_params);
 
 void cdef_copy_rect8_16bit_to_16bit_c(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
 void cdef_copy_rect8_16bit_to_16bit_sse2(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
diff --git a/third_party/libaom/source/config/win/x64/config/av1_rtcd.h b/third_party/libaom/source/config/win/x64/config/av1_rtcd.h
index efc39dae..0c01a89c 100644
--- a/third_party/libaom/source/config/win/x64/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/win/x64/config/av1_rtcd.h
@@ -554,10 +554,51 @@
 uint64_t av1_wedge_sse_from_residuals_avx2(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 RTCD_EXTERN uint64_t (*av1_wedge_sse_from_residuals)(const int16_t *r1, const int16_t *d, const uint8_t *m, int N);
 
-void av1_wiener_convolve_add_src_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-void av1_wiener_convolve_add_src_sse2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-void av1_wiener_convolve_add_src_avx2(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
-RTCD_EXTERN void (*av1_wiener_convolve_add_src)(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h, const ConvolveParams *conv_params);
+void av1_wiener_convolve_add_src_c(const uint8_t* src,
+                                   ptrdiff_t src_stride,
+                                   uint8_t* dst,
+                                   ptrdiff_t dst_stride,
+                                   const int16_t* filter_x,
+                                   int x_step_q4,
+                                   const int16_t* filter_y,
+                                   int y_step_q4,
+                                   int w,
+                                   int h,
+                                   const WienerConvolveParams* conv_params);
+void av1_wiener_convolve_add_src_sse2(const uint8_t* src,
+                                      ptrdiff_t src_stride,
+                                      uint8_t* dst,
+                                      ptrdiff_t dst_stride,
+                                      const int16_t* filter_x,
+                                      int x_step_q4,
+                                      const int16_t* filter_y,
+                                      int y_step_q4,
+                                      int w,
+                                      int h,
+                                      const WienerConvolveParams* conv_params);
+void av1_wiener_convolve_add_src_avx2(const uint8_t* src,
+                                      ptrdiff_t src_stride,
+                                      uint8_t* dst,
+                                      ptrdiff_t dst_stride,
+                                      const int16_t* filter_x,
+                                      int x_step_q4,
+                                      const int16_t* filter_y,
+                                      int y_step_q4,
+                                      int w,
+                                      int h,
+                                      const WienerConvolveParams* conv_params);
+RTCD_EXTERN void (*av1_wiener_convolve_add_src)(
+    const uint8_t* src,
+    ptrdiff_t src_stride,
+    uint8_t* dst,
+    ptrdiff_t dst_stride,
+    const int16_t* filter_x,
+    int x_step_q4,
+    const int16_t* filter_y,
+    int y_step_q4,
+    int w,
+    int h,
+    const WienerConvolveParams* conv_params);
 
 void cdef_copy_rect8_16bit_to_16bit_c(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
 void cdef_copy_rect8_16bit_to_16bit_sse2(uint16_t *dst, int dstride, const uint16_t *src, int sstride, int width, int height);
diff --git a/third_party/libaom/source/libaom b/third_party/libaom/source/libaom
index 1dbe1c7..7b5f665 160000
--- a/third_party/libaom/source/libaom
+++ b/third_party/libaom/source/libaom
@@ -1 +1 @@
-Subproject commit 1dbe1c7fae2456f91ccc79fecb919e9ffea0727a
+Subproject commit 7b5f665231dfbcc5abc49d3b8d6d8826c75ce473
diff --git a/third_party/libpng/BUILD.gn b/third_party/libpng/BUILD.gn
index 1ba886f..b967f5c6 100644
--- a/third_party/libpng/BUILD.gn
+++ b/third_party/libpng/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/arm.gni")
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/mips.gni")
 
 if (build_with_chromium) {
diff --git a/third_party/lottie/lottie_worker.js b/third_party/lottie/lottie_worker.js
index ffe18ab..29dffcc 100644
--- a/third_party/lottie/lottie_worker.js
+++ b/third_party/lottie/lottie_worker.js
@@ -1638,6 +1638,7 @@
             comps[i].layers.__used = true;
             return comps[i].layers;
           }
+          // eslint-disable-next-line no-restricted-syntax
           return JSON.parse(JSON.stringify(comps[i].layers));
         }
         i += 1;
@@ -4417,6 +4418,7 @@
   RepeaterModifier.prototype.cloneElements = function(elements) {
     let i;
     const len = elements.length;
+    // eslint-disable-next-line no-restricted-syntax
     const newElements = JSON.parse(JSON.stringify(elements));
     this.resetElements(newElements);
     return newElements;
diff --git a/third_party/minigbm/BUILD.gn b/third_party/minigbm/BUILD.gn
index 739e278..31ee617 100644
--- a/third_party/minigbm/BUILD.gn
+++ b/third_party/minigbm/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/linux/pkg_config.gni")
 
diff --git a/third_party/perfetto b/third_party/perfetto
index 79b45f6..33063c94 160000
--- a/third_party/perfetto
+++ b/third_party/perfetto
@@ -1 +1 @@
-Subproject commit 79b45f60dfbe97cbbc8f8be3a3807ae186bfd60a
+Subproject commit 33063c9403c381f5411e1cddf8688a912529b4d9
diff --git a/third_party/skia b/third_party/skia
index 77aeee3..2b21838 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit 77aeee3b81a5792a1338a28b1a24dc6c1ebada58
+Subproject commit 2b218381e226d986a9b43789d8822b1ce4d80516
diff --git a/third_party/webrtc b/third_party/webrtc
index 9272771..be04c98 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit 9272771418491e6ec56d6ea11167d1d1cbf2b81f
+Subproject commit be04c98d6488fc86594424e39c16d849f8628e27
diff --git a/third_party/webrtc_overrides/BUILD.gn b/third_party/webrtc_overrides/BUILD.gn
index 8f2430e..e726b676 100644
--- a/third_party/webrtc_overrides/BUILD.gn
+++ b/third_party/webrtc_overrides/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//third_party/webrtc/webrtc.gni")
 
 if (is_android) {
diff --git a/tools/ipc_fuzzer/ipc_fuzzer.gni b/tools/ipc_fuzzer/ipc_fuzzer.gni
index bee9a0b..adea488 100644
--- a/tools/ipc_fuzzer/ipc_fuzzer.gni
+++ b/tools/ipc_fuzzer/ipc_fuzzer.gni
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 import("//build/config/ui.gni")
 
diff --git a/tools/json_schema_compiler/cpp_type_generator.py b/tools/json_schema_compiler/cpp_type_generator.py
index 6f021a71..5328687 100644
--- a/tools/json_schema_compiler/cpp_type_generator.py
+++ b/tools/json_schema_compiler/cpp_type_generator.py
@@ -87,11 +87,18 @@
       x86_64: kX86_64
       x86_ARCH: kX86Arch
       '': EmptyString
+      kConstantSupport: kConstantSupport.
     """
 
     if not name:
       return 'EmptyString'
 
+    # For cases where the enum entry is something like kValue, an exception is
+    # made to drop the initial `k` to avoid generating a key that looks like
+    # kKvalue, which is less readable than kValue.
+    if len(name) > 1 and name.startswith('k') and name[1].isupper():
+      name = name[1:]
+
     change_to_upper = True
     last_was_lower = True
     result = ''
diff --git a/tools/json_schema_compiler/test/enums.json b/tools/json_schema_compiler/test/enums.json
index 717f158..8293329 100644
--- a/tools/json_schema_compiler/test/enums.json
+++ b/tools/json_schema_compiler/test/enums.json
@@ -68,6 +68,7 @@
                 "sixth-entry-example",
                 "Seventh_entry86_64_example",
                 "Eighth_entry86_ARCH_example",
+                "kNinthEntryExample",
                 ""]
       }
     ],
diff --git a/tools/json_schema_compiler/test/enums_unittest.cc b/tools/json_schema_compiler/test/enums_unittest.cc
index bfa4f4d4..e293bbb 100644
--- a/tools/json_schema_compiler/test/enums_unittest.cc
+++ b/tools/json_schema_compiler/test/enums_unittest.cc
@@ -296,6 +296,8 @@
             enums::ParseEnumNameTransformation("Seventh_entry86_64_example"));
   EXPECT_EQ(enums::EnumNameTransformation::kEighthEntry86ArchExample,
             enums::ParseEnumNameTransformation("Eighth_entry86_ARCH_example"));
+  EXPECT_EQ(enums::EnumNameTransformation::kNinthEntryExample,
+            enums::ParseEnumNameTransformation("kNinthEntryExample"));
   EXPECT_EQ(enums::EnumNameTransformation::kEmptyString,
             enums::ParseEnumNameTransformation(""));
 }
diff --git a/tools/metrics/histograms/README.md b/tools/metrics/histograms/README.md
index a0df808b..efd12bc7 100644
--- a/tools/metrics/histograms/README.md
+++ b/tools/metrics/histograms/README.md
@@ -706,7 +706,7 @@
 Delete the entry in the histograms.xml file.
 
 * In some cases there may be artifacts that remain, with some examples being:
-  * Empty `<token>` blocks.
+  * Empty `<token>` blocks, or individual `<variant>`s.
   * `<enum>` blocks from enums.xml that are no longer used.
   * Suffix entries in histogram_suffixes_list.xml.
 * Please remove these artifacts if you find them.
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 014d248..d84eb8a 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -6626,12 +6626,6 @@
   <int value="273" label="ClearLocalCvcs: Failure"/>
 </enum>
 
-<enum name="AutomaticBeaconOutcome">
-  <int value="0" label="Success"/>
-  <int value="1" label="No transient user activation"/>
-  <int value="2" label="Initiator frame not same-origin with mapped URL"/>
-</enum>
-
 <enum name="AutomaticLazyFrameLoadReason">
   <int value="0" label="Not eligible"/>
   <int value="1" label="Eligible for LazyEmbeds"/>
@@ -12142,7 +12136,8 @@
   <int value="79" label="Javascript JIT"/>
   <int value="80" label="HTTP allowed"/>
   <int value="81" label="Formfill metadata"/>
-  <int value="82" label="Federated identity active session"/>
+  <int value="82"
+      label="Federated identity active session (Obsolete Nov 2023)"/>
   <int value="83" label="Auto-darken web content"/>
   <int value="84" label="Request desktop site"/>
   <int value="85" label="Federated identity browser JavaScript API"/>
@@ -19408,23 +19403,6 @@
   <int value="1" label="Server redirect"/>
 </enum>
 
-<enum name="DirectActionId">
-  <int value="0" label="Unknown action"/>
-  <int value="1" label="A direct action not on this enum"/>
-  <int value="2" label="go_back"/>
-  <int value="3" label="reload"/>
-  <int value="4" label="go_forward"/>
-  <int value="5" label="bookmark_this_page"/>
-  <int value="6" label="downloads"/>
-  <int value="7" label="preferences"/>
-  <int value="8" label="open_history"/>
-  <int value="9" label="help"/>
-  <int value="10" label="new_tab"/>
-  <int value="11" label="close_tab"/>
-  <int value="12" label="close_all_tabs"/>
-  <int value="13" label="find_in_page"/>
-</enum>
-
 <enum name="DirectCompositionVideoPresentationMode">
   <int value="0" label="Zero copy decode swap chain"/>
   <int value="1" label="Upload and video processor blit"/>
@@ -26901,6 +26879,7 @@
       label="OS_DIAGNOSTICS_ISVOLUMEBUTTONROUTINEARGUMENTSUPPORTED"/>
   <int value="1838" label="USERSCRIPTS_CONFIGUREWORLD"/>
   <int value="1839" label="ENTERPRISE_KIOSKINPUT_SETCURRENTINPUTMETHOD"/>
+  <int value="1840" label="AUTOFILLPRIVATE_BULKDELETEALLCVCS"/>
 </enum>
 
 <enum name="ExtensionInProgressRequestState">
@@ -27349,6 +27328,8 @@
   <int value="5" label="LEGACY_PACKAGED_APP"/>
   <int value="6" label="PLATFORM_APP"/>
   <int value="7" label="SHARED_MODULE"/>
+  <int value="8" label="LOGIN_SCREEN_EXTENSION"/>
+  <int value="9" label="CHROMEOS_SYSTEM_EXTENSION"/>
 </enum>
 
 <enum name="ExtensionUninstallSource">
@@ -27361,6 +27342,8 @@
   <int value="6" label="Chrome apps page"/>
   <int value="7" label="Chrome extensions page"/>
   <int value="8" label="Extension"/>
+  <int value="9" label="Chrome Webstore"/>
+  <int value="10" label="Hosted app menu"/>
 </enum>
 
 <enum name="ExtensionUnpackFailureReason">
@@ -32297,8 +32280,8 @@
   <int value="4222" label="OBSOLETE_GestureScrollEnd"/>
   <int value="4223" label="ArrayBufferTooBigForWebAPI"/>
   <int value="4224" label="FedCmRevoke"/>
-  <int value="4225" label="FedCmLogout"/>
-  <int value="4226" label="FedCmLogoutRps"/>
+  <int value="4225" label="OBSOLETE_FedCmLogout"/>
+  <int value="4226" label="OBSOLETE_FedCmLogoutRps"/>
   <int value="4227" label="V8Navigator_DeprecatedReplaceInURN_Method"/>
   <int value="4228" label="WebAppBorderless"/>
   <int value="4229" label="PaymentInstruments"/>
@@ -59877,6 +59860,7 @@
   <int value="12" label="Guest OS Files"/>
   <int value="100" label="Unknown"/>
   <int value="101" label="Microsoft OneDrive"/>
+  <int value="102" label="Android OneDrive Documents Provider"/>
 </enum>
 
 <enum name="OfficeFilesTransferRequired">
@@ -60852,6 +60836,7 @@
   <int value="29" label="Wi-Fi: Hidden Network"/>
   <int value="30" label="Hotspot: On/Off"/>
   <int value="31" label="Hotspot: Automatically Turn Off Hotspot"/>
+  <int value="32" label="Cellular APN: Add APN"/>
   <int value="100" label="Bluetooth: On/Off"/>
   <int value="101" label="Bluetooth: Connect To Device"/>
   <int value="102" label="Bluetooth: Disconnect From Device"/>
diff --git a/tools/metrics/histograms/find_unmapped_histograms.py b/tools/metrics/histograms/find_unmapped_histograms.py
index e687590..94afcda 100755
--- a/tools/metrics/histograms/find_unmapped_histograms.py
+++ b/tools/metrics/histograms/find_unmapped_histograms.py
@@ -80,7 +80,8 @@
     ){2,}                         # Group repeated 2 or more times
     $                             # End of string
     """, re.VERBOSE)
-HISTOGRAM_REGEX = re.compile(r"""
+HISTOGRAM_MACRO_REGEX = re.compile(
+    r"""
     (\w*           # Capture the whole macro name
     UMA_HISTOGRAM_ # Match the shared prefix for standard UMA histogram macros
     (\w*))         # Match the rest of the macro name, e.g. '_ENUMERATION'
@@ -89,8 +90,18 @@
     ([^,)]*)       # Capture the first parameter to the macro
     [,)]           # Match the comma/paren that delineates the first parameter
     """, re.VERBOSE)
-# Note: Order matches histogram_macros.h.
-STANDARD_HISTOGRAM_SUFFIXES = frozenset([
+HISTOGRAM_FUNCTION_REGEX = re.compile(
+    r"""
+    (\w*           # Capture the whole function name
+    UmaHistogram   # Match the shared prefix for UMA histogram functions
+    (\w*))         # Match the rest of the macro name, e.g. 'Enumeration'
+    \(             # Match the opening parenthesis for the macro
+    \s*            # Match any whitespace -- especially, any newlines
+    ([^,)]*)       # Capture the first parameter to the macro
+    [,)]           # Match the comma/paren that delineates the first parameter
+    """, re.VERBOSE)
+HISTOGRAM_MACRO_SUFFIXES = frozenset([
+    # Note: Order matches histogram_macros.h.
     'ENUMERATION',
     'SCALED_ENUMERATION',
     'BOOLEAN',
@@ -116,15 +127,8 @@
     'SPARSE',
     'COUNTS',
     'MEMORY_MB',
-])
-OTHER_STANDARD_HISTOGRAMS = frozenset([
-    'SCOPED_UMA_HISTOGRAM_TIMER',
-    'SCOPED_UMA_HISTOGRAM_LONG_TIMER',
-    'SCOPED_UMA_HISTOGRAM_TIMER_MICROS',
-])
-# The following suffixes are not defined in //base/metrics but the first
-# argument to the macro is the full name of the histogram as a literal string.
-STANDARD_LIKE_SUFFIXES = frozenset([
+    'CUSTOM_ENUMERATION',
+    # The following suffixes are not defined in //base/metrics.
     'SCROLL_LATENCY_SHORT',
     'SCROLL_LATENCY_LONG',
     'TOUCH_TO_SCROLL_LATENCY',
@@ -142,7 +146,38 @@
     'LOCK_TIMES',
     'OOM_KILL_TIME_INTERVAL',
 ])
-OTHER_STANDARD_LIKE_HISTOGRAMS = frozenset(['SCOPED_BLINK_UMA_HISTOGRAM_TIMER'])
+OTHER_HISTOGRAM_MACROS = frozenset([
+    'SCOPED_UMA_HISTOGRAM_TIMER',
+    'SCOPED_UMA_HISTOGRAM_LONG_TIMER',
+    'SCOPED_UMA_HISTOGRAM_TIMER_MICROS',
+    'SCOPED_BLINK_UMA_HISTOGRAM_TIMER',
+])
+HISTOGRAM_FUNCTION_SUFFIXES = frozenset([
+    # Note: Order matches histogram_functions.h.
+    'ExactLinear',
+    'Enumeration',
+    'Boolean',
+    'Percentage',
+    'PercentageObsoleteDoNotUse',
+    'CustomCounts',
+    'Counts100',
+    'Counts1000',
+    'Counts10000',
+    'Counts100000',
+    'Counts1M',
+    'Counts10M',
+    'CustomTimes',
+    'Times',
+    'MediumTimes',
+    'LongTimes',
+    'LongTimes100',
+    'CustomMicrosecondsTimes',
+    'MicrosecondsTimes',
+    'MemoryKB',
+    'MemoryMB',
+    'MemoryLargeMB',
+    'Sparse',
+])
 
 
 def RunGit(command):
@@ -165,7 +200,7 @@
     return self.msg
 
 
-def keepOnlyNewlines(match_object):
+def keep_only_newlines(match_object):
   """Remove everything from a matched string except for the newline characters.
   Takes a MatchObject argument so that it can be used directly as the repl
   argument to re.sub().
@@ -181,7 +216,7 @@
   return NON_NEWLINE.sub('', match_object.group(0))
 
 
-def removeComments(string):
+def remove_comments(string):
   """Remove any comments from an expression, including leading and trailing
   whitespace. This does not correctly ignore comments embedded in strings, but
   that shouldn't matter for this script. Newlines in the removed text are
@@ -195,10 +230,10 @@
     The string with comments removed, e.g. '"\nMy.Important.Counts" '
 
   """
-  return CPP_COMMENT.sub(keepOnlyNewlines, string)
+  return CPP_COMMENT.sub(keep_only_newlines, string)
 
 
-def collapseAdjacentCStrings(string):
+def collapse_adjacent_c_strings(string):
   """Collapses any adjacent C strings into a single string.
 
   Useful to re-combine strings that were split across multiple lines to satisfy
@@ -218,7 +253,7 @@
     string = collapsed
 
 
-def logNonLiteralHistogram(filename, histogram):
+def log_non_literal_histogram(filename, symbol_name, histogram):
   """Logs a statement warning about a non-literal histogram name found in the
   Chromium source.
 
@@ -227,6 +262,7 @@
   Args:
     filename: The filename for the file containing the histogram, e.g.
               'chrome/browser/memory_details.cc'
+    symbol_name: The function/macro name called.
     histogram: The expression that evaluates to the name of the histogram, e.g.
                '"FakeHistogram" + variant'
 
@@ -252,14 +288,14 @@
 
   # TODO(isherman): This is still a little noisy... needs further filtering to
   # reduce the noise.
-  logging.warning('%s contains non-literal histogram name <%s>', filename,
-                  histogram)
+  logging.warning('%s: %s used with non-literal histogram name <%s>', filename,
+                  symbol_name, histogram)
 
 
-def readChromiumHistograms():
+def read_chromium_histograms():
   """Searches the Chromium source for all histogram names.
 
-  Also prints warnings for any invocations of the UMA_HISTOGRAM_* macros with
+  Prints warnings for any invocations of the UMA_HISTOGRAM_* macros with
   names that might vary during a single run of the app.
 
   Returns:
@@ -267,63 +303,100 @@
       a set containing any found literal histogram names, and
       a set mapping histogram name to first filename:line where it was found
   """
-  logging.info('Scanning Chromium source for histograms...')
+  # Note: For functions, we don't require literals (no warnings printed), but
+  # we also are limited to finding unmapped names coming from literals.
+  logging.info('Scanning Chromium source for histograms functions...')
+  histograms, location_map = find_histograms('UmaHistogram',
+                                             HISTOGRAM_FUNCTION_REGEX,
+                                             HISTOGRAM_FUNCTION_SUFFIXES, [],
+                                             require_literals=False)
 
+  logging.info('Scanning Chromium source for histograms macros...')
+  histograms2, location_map2 = find_histograms('UMA_HISTOGRAM',
+                                               HISTOGRAM_MACRO_REGEX,
+                                               HISTOGRAM_MACRO_SUFFIXES,
+                                               OTHER_HISTOGRAM_MACROS,
+                                               require_literals=True)
+
+  histograms.update(histograms2)
+  location_map.update(location_map2)
+  return histograms, location_map
+
+
+def find_histograms(grep_expression, regex, all_suffixes, all_others,
+                    require_literals):
+  """Searches the Chromium source for histogram names.
+
+  If `regex` is 'UMA_HISTOGRAM', prints warnings for any invocations the macros
+  with names that might vary during a single run of the app.
+
+  Args:
+    grep_expression: Either 'UMA_HISTOGRAM' or 'UmaHistogram' as the expression
+      to pass to "git gs" for searching for relevant lines.
+    regex: The actual regex to find call sites.
+    all_suffixes: Suffixes to look for.
+    all_others: Other macros/functions to look for.
+    require_literals: Whether errors should be printed about non-literal args.
+
+  Returns:
+    A tuple of
+      a set containing any found literal histogram names, and
+      a set mapping histogram name to first filename:line where it was found
+  """
   # Use git grep to find all invocations of the UMA_HISTOGRAM_* macros.
   # Examples:
   #   'path/to/foo.cc:420:  UMA_HISTOGRAM_COUNTS_100("FooGroup.FooName",'
   #   'path/to/bar.cc:632:  UMA_HISTOGRAM_ENUMERATION('
-  locations = RunGit(['gs', 'UMA_HISTOGRAM']).split('\n')
+  locations = RunGit(['gs', grep_expression]).split('\n')
   all_filenames = set(location.split(':')[0] for location in locations);
   filenames = [f for f in all_filenames
                if C_FILENAME.match(f) and not TEST_FILENAME.match(f)]
 
   histograms = set()
   location_map = dict()
-  unknown_macros = set()
-  all_suffixes = STANDARD_HISTOGRAM_SUFFIXES | STANDARD_LIKE_SUFFIXES
-  all_others = OTHER_STANDARD_HISTOGRAMS | OTHER_STANDARD_LIKE_HISTOGRAMS
+  unknown_symbols = set()
   for filename in filenames:
     contents = ''
     with open(filename, 'r') as f:
-      contents = removeComments(f.read())
+      contents = remove_comments(f.read())
 
-    # TODO(isherman): Look for histogram function calls like
-    # base::UmaHistogramSparse() in addition to macro invocations.
-    for match in HISTOGRAM_REGEX.finditer(contents):
+    for match in regex.finditer(contents):
       line_number = contents[:match.start()].count('\n') + 1
-      if (match.group(2) not in all_suffixes and
-          match.group(1) not in all_others):
-        full_macro_name = match.group(1)
-        if (full_macro_name not in unknown_macros):
-          logging.warning('%s:%d: Unknown macro name: <%s>' %
-                          (filename, line_number, match.group(1)))
-          unknown_macros.add(full_macro_name)
+      full_symbol_name = match.group(1)
+      symbol_suffix = match.group(2)
+      metric_name = collapse_adjacent_c_strings(match.group(3).strip())
 
+      if (symbol_suffix not in all_suffixes
+          and full_symbol_name not in all_others):
+        if (full_symbol_name not in unknown_symbols):
+          logging.warning('%s:%d: Unknown symbol name: <%s>' %
+                          (filename, line_number, match.group(1)))
+          unknown_symbols.add(full_symbol_name)
         continue
 
-      histogram = match.group(3).strip()
-      histogram = collapseAdjacentCStrings(histogram)
-
       # Must begin and end with a quotation mark.
-      if not histogram or histogram[0] != '"' or histogram[-1] != '"':
-        logNonLiteralHistogram(filename, histogram)
+      if not metric_name or metric_name[0] != '"' or metric_name[-1] != '"':
+        if require_literals:
+          log_non_literal_histogram(filename, full_symbol_name, metric_name)
+        # Not a literal name. Skip.
         continue
 
       # Must not include any quotation marks other than at the beginning or end.
-      histogram_stripped = histogram.strip('"')
-      if '"' in histogram_stripped:
-        logNonLiteralHistogram(filename, histogram)
+      metric_name_stripped = metric_name.strip('"')
+      if '"' in metric_name_stripped:
+        if require_literals:
+          log_non_literal_histogram(filename, full_symbol_name, metric_name)
+        # Not a literal name. Skip.
         continue
 
-      if histogram_stripped not in histograms:
-        histograms.add(histogram_stripped)
-        location_map[histogram_stripped] = '%s:%d' % (filename, line_number)
+      if metric_name_stripped not in histograms:
+        histograms.add(metric_name_stripped)
+        location_map[metric_name_stripped] = '%s:%d' % (filename, line_number)
 
   return histograms, location_map
 
 
-def readAllXmlHistograms():
+def read_all_xml_histograms():
   """Parses all histogram names defined in |histogram_paths.ALL_XMLS|.
 
   Returns:
@@ -334,7 +407,7 @@
   return set(extract_histograms.ExtractNames(histograms))
 
 
-def readXmlHistograms(histograms_file_location):
+def read_xml_histograms(histograms_file_location):
   """Parses all histogram names from |histograms_file_location|.
 
   Args:
@@ -348,7 +421,7 @@
   return set(extract_histograms.ExtractNames(histograms))
 
 
-def hashHistogramName(name):
+def hash_histogram_name(name):
   """Computes the hash of a histogram name.
 
   Args:
@@ -365,8 +438,8 @@
     parts = location_map[histogram].split(':')
     assert len(parts) == 2
     (filename, line_number) = parts
-    print('%s,%s,%s,%s' % (filename, line_number, histogram,
-                           hashHistogramName(histogram)))
+    print('%s,%s,%s,%s' %
+          (filename, line_number, histogram, hash_histogram_name(histogram)))
 
 
 def output_log(unmapped_histograms, location_map, verbose):
@@ -378,9 +451,9 @@
     for histogram in sorted(unmapped_histograms):
       if verbose:
         logging.info('%s: %s - %s', location_map[histogram], histogram,
-                     hashHistogramName(histogram))
+                     hash_histogram_name(histogram))
       else:
-        logging.info('  %s - %s', histogram, hashHistogramName(histogram))
+        logging.info('  %s - %s', histogram, hash_histogram_name(histogram))
   else:
     logging.info('Success!  No unmapped histograms found.')
 
@@ -428,12 +501,13 @@
   except EnvironmentError as e:
     logging.error("Could not change to root directory: %s", e)
     sys.exit(1)
-  chromium_histograms, location_map = readChromiumHistograms()
-  xml_histograms = readAllXmlHistograms()
+  chromium_histograms, location_map = read_chromium_histograms()
+  xml_histograms = read_all_xml_histograms()
   unmapped_histograms = chromium_histograms - xml_histograms
 
   if os.path.isfile(options.extra_histograms_file_location):
-    xml_histograms2 = readXmlHistograms(options.extra_histograms_file_location)
+    xml_histograms2 = read_xml_histograms(
+        options.extra_histograms_file_location)
     unmapped_histograms -= xml_histograms2
   else:
     logging.warning('No such file: %s', options.extra_histograms_file_location)
diff --git a/tools/metrics/histograms/histograms_index.txt b/tools/metrics/histograms/histograms_index.txt
index fcb854e..c9616acc 100644
--- a/tools/metrics/histograms/histograms_index.txt
+++ b/tools/metrics/histograms/histograms_index.txt
@@ -89,6 +89,7 @@
 tools/metrics/histograms/metadata/memory/histograms.xml
 tools/metrics/histograms/metadata/mobile/histograms.xml
 tools/metrics/histograms/metadata/na_cl/histograms.xml
+tools/metrics/histograms/metadata/navigation/enums.xml
 tools/metrics/histograms/metadata/navigation/histograms.xml
 tools/metrics/histograms/metadata/nearby/histograms.xml
 tools/metrics/histograms/metadata/net/histograms.xml
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index fd1d2dec..5a9ff3e 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -1021,17 +1021,6 @@
   </summary>
 </histogram>
 
-<histogram name="Android.DirectAction.Perform" enum="DirectActionId"
-    expires_after="2023-10-10">
-  <owner>arbesser@google.com</owner>
-  <owner>autofill_assistant@google.com</owner>
-  <summary>
-    Counts calls to Activity.onPerformDirectAction made by the system on behalf
-    of the assist app and which action was performed, if any. Available starting
-    with Android Q.
-  </summary>
-</histogram>
-
 <histogram name="Android.Download.Rename.Dialog.Action"
     enum="Android.Download.Rename.Dialog.Action" expires_after="2021-08-09">
   <obsolete>
@@ -3756,7 +3745,7 @@
 </histogram>
 
 <histogram name="Android.RestoreTabsOnFRE.ResultActionFirstShow"
-    enum="RestoreTabsOnFREResultAction" expires_after="2023-12-15">
+    enum="RestoreTabsOnFREResultAction" expires_after="2024-03-31">
   <owner>ckitagawa@chromium.org</owner>
   <owner>bjfong@google.com</owner>
   <owner>fredmello@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/arc/enums.xml b/tools/metrics/histograms/metadata/arc/enums.xml
index d892c244c..4fb8aea 100644
--- a/tools/metrics/histograms/metadata/arc/enums.xml
+++ b/tools/metrics/histograms/metadata/arc/enums.xml
@@ -216,6 +216,19 @@
   <int value="6" label="Not allowed"/>
 </enum>
 
+<enum name="ArcFeaturesParseResult">
+  <int value="0" label="kSuccess"/>
+  <int value="1" label="kErrorParsingJson"/>
+  <int value="2" label="kInvalidFeatureList"/>
+  <int value="3" label="kInvalidUnavailableFeatureList"/>
+  <int value="4" label="kInvalidPropertiesList"/>
+  <int value="5" label="kMissingFingerprintProperty"/>
+  <int value="6" label="kMissingSdkProperty"/>
+  <int value="7" label="kMissingReleaseProperty"/>
+  <int value="8" label="kMissingAbiListProperty"/>
+  <int value="9" label="kMissingPlayStoreVersion"/>
+</enum>
+
 <enum name="ArcFileSystemWatcherExceedLimitState">
   <int value="0"
       label="inotify exceeds its limit when ArcFileSystemWatcher is started"/>
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml
index ef23187..8033c442 100644
--- a/tools/metrics/histograms/metadata/arc/histograms.xml
+++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -692,6 +692,17 @@
   </summary>
 </histogram>
 
+<histogram name="Arc.ArcFeatures.ParseResult" enum="ArcFeaturesParseResult"
+    expires_after="2024-11-01">
+  <owner>tsergeant@chromium.org</owner>
+  <owner>chromeos-apps-foundation-team@google.com</owner>
+  <summary>
+    Records the result of parsing the ARC Features JSON file off rootfs.
+    Recorded every time the file is parsed, which most commonly happens during
+    OOBE.
+  </summary>
+</histogram>
+
 <histogram name="Arc.Auth.AccountCheck.Status{ArcUserTypes}"
     enum="ArcAuthAccountCheckStatus" expires_after="never">
 <!-- expires-never: Needed for long-term health monitoring of ARC provisioning. -->
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml
index c12aa410..8c84963 100644
--- a/tools/metrics/histograms/metadata/ash/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -4949,6 +4949,27 @@
 </histogram>
 
 <histogram
+    name="Ash.NotifierFramework.{UnpinnedOrPinned}SystemNotification.ClickedActionButton.{ButtonIndex}"
+    enum="NotificationCatalogName" expires_after="2024-03-17">
+  <owner>kradtke@google.com</owner>
+  <owner>cros-status-area-eng@google.com</owner>
+  <summary>
+    Tracks action button presses on system notifications. Records the
+    notification catalog name in one of the button index buckets.
+  </summary>
+  <token key="UnpinnedOrPinned">
+    <variant name=""/>
+    <variant name="Pinned"/>
+  </token>
+  <token key="ButtonIndex">
+    <variant name="1"/>
+    <variant name="2"/>
+    <variant name="3"/>
+    <variant name="4"/>
+  </token>
+</histogram>
+
+<histogram
     name="Ash.NotifierFramework.{UnpinnedOrPinned}SystemNotification.Popup.Dismissed.{TimeRange}"
     enum="NotificationCatalogName" expires_after="2024-03-17">
   <owner>kradtke@google.com</owner>
@@ -6564,10 +6585,6 @@
 
 <histogram name="Ash.Smoothness.PercentDroppedFrames_1sWindow{Stage}" units="%"
     expires_after="2023-10-30">
-  <obsolete>
-    This metric is reported on every dropped frame instead of every frame. It is
-    deprecated in favor of Ash.Smoothness.PercentDroppedFrames_1sWindow2.
-  </obsolete>
   <owner>xiyuan@chromium.org</owner>
   <owner>cros-sw-perf@google.com</owner>
   <summary>
@@ -7627,6 +7644,17 @@
   </summary>
 </histogram>
 
+<histogram name="Ash.Wallpaper.Online.Result" enum="SetWallpaperResult"
+    expires_after="2023-08-31">
+  <owner>jasontt@chromium.org</owner>
+  <owner>assistive-eng@google.com</owner>
+  <summary>
+    Tracks the result of user's attempt to set a wallpaper. Recorded when a user
+    selects a wallpaper from the personalization hub. b/285387348: Add more
+    variants and fix incorrect metric recording for online wallpapers.
+  </summary>
+</histogram>
+
 <histogram name="Ash.Wallpaper.Preview.Show" enum="BooleanHit"
     expires_after="2024-02-13">
   <owner>jasontt@chromium.org</owner>
@@ -7660,25 +7688,6 @@
   </summary>
 </histogram>
 
-<histogram name="Ash.Wallpaper.{WallpaperType}.Result"
-    enum="SetWallpaperResult" expires_after="2023-08-31">
-  <obsolete>
-    Replaced Aug 2023 by Ash.Wallpaper.{WallpaperType}.Result2.
-  </obsolete>
-  <owner>jasontt@chromium.org</owner>
-  <owner>assistive-eng@google.com</owner>
-  <summary>
-    Tracks the result of user's attempt to set a wallpaper. Recorded when a user
-    selects a wallpaper from the personalization hub. b/285387348: Add more
-    variants and fix incorrect metric recording for online wallpapers.
-  </summary>
-  <token key="WallpaperType">
-    <variant name="Customized"/>
-    <variant name="OnceGooglePhotos"/>
-    <variant name="Online"/>
-  </token>
-</histogram>
-
 <histogram name="Ash.Wallpaper.{WallpaperType}.Result2"
     enum="SetWallpaperResult" expires_after="2024-08-15">
   <owner>thuongphan@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml
index 31db4a8..8b6d580 100644
--- a/tools/metrics/histograms/metadata/autofill/histograms.xml
+++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -5170,9 +5170,6 @@
 
 <histogram name="Autofill.UnmaskPrompt.Events" enum="AutofillUnmaskPromptEvent"
     expires_after="2023-03-19">
-  <obsolete>
-    Deprecated in M109. Subsumed by Autofill.UnmaskPrompt.{CardType}.Events.
-  </obsolete>
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/chrome/histograms.xml b/tools/metrics/histograms/metadata/chrome/histograms.xml
index b1e185c..9c6da9d 100644
--- a/tools/metrics/histograms/metadata/chrome/histograms.xml
+++ b/tools/metrics/histograms/metadata/chrome/histograms.xml
@@ -140,11 +140,6 @@
 
 <histogram name="Chrome.Lacros.Smoothness.PercentDroppedFrames_1sWindow"
     units="%" expires_after="2023-07-25">
-  <obsolete>
-    This metric is reported on every dropped frame instead of every frame. It is
-    deprecated in favor of
-    Chrome.Lacros.Smoothness.PercentDroppedFrames_1sWindow2
-  </obsolete>
   <owner>xiyuan@chromium.org</owner>
   <owner>cros-sw-perf@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/companion/histograms.xml b/tools/metrics/histograms/metadata/companion/histograms.xml
index 3842856..4a55520 100644
--- a/tools/metrics/histograms/metadata/companion/histograms.xml
+++ b/tools/metrics/histograms/metadata/companion/histograms.xml
@@ -148,6 +148,17 @@
   </summary>
 </histogram>
 
+<histogram name="Companion.VisualQuery.Agent.DomImageCount" units="images"
+    expires_after="2024-03-31">
+  <owner>srna@google.com</owner>
+  <owner>pstjuste@google.com</owner>
+  <owner>src/chrome/browser/companion/OWNERS</owner>
+  <summary>
+    Records the number of images on the page found by DOM traversal. Recorded
+    during classification start for VisualQuerySuggestions in CSC.
+  </summary>
+</histogram>
+
 <histogram name="Companion.VisualQuery.Agent.StartClassification"
     enum="Boolean" expires_after="2024-04-28">
   <owner>srna@google.com</owner>
@@ -220,17 +231,6 @@
   </summary>
 </histogram>
 
-<histogram name="Companion.VisualQuery.DomImageCount" units="images"
-    expires_after="2024-03-31">
-  <owner>srna@google.com</owner>
-  <owner>pstjuste@google.com</owner>
-  <owner>src/chrome/browser/companion/OWNERS</owner>
-  <summary>
-    Records the number of images on the page found by DOM traversal. Recorded
-    during classification start for VisualQuerySuggestions in CSC.
-  </summary>
-</histogram>
-
 <histogram name="Companion.VisualQuery.EligibilityStatus.NumImages"
     units="images" expires_after="2024-04-28">
   <owner>srna@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/cross_device/histograms.xml b/tools/metrics/histograms/metadata/cross_device/histograms.xml
index adfb73b..a207083f 100644
--- a/tools/metrics/histograms/metadata/cross_device/histograms.xml
+++ b/tools/metrics/histograms/metadata/cross_device/histograms.xml
@@ -1119,9 +1119,6 @@
 
 <histogram name="EasyUnlock.AuthEvent.SignIn" enum="EasyUnlockAuthEvent"
     expires_after="2023-12-31">
-  <obsolete>
-    Sign in with Smart Lock deprecated.
-  </obsolete>
   <owner>hansberry@chromium.org</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
   <summary>
@@ -1134,9 +1131,6 @@
 
 <histogram name="EasyUnlock.AuthEvent.SignIn.Duration" units="ms"
     expires_after="2023-12-31">
-  <obsolete>
-    Sign in with Smart Lock deprecated.
-  </obsolete>
   <owner>hansberry@chromium.org</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/geolocation/histograms.xml b/tools/metrics/histograms/metadata/geolocation/histograms.xml
index d09ba28f61..0d26a11 100644
--- a/tools/metrics/histograms/metadata/geolocation/histograms.xml
+++ b/tools/metrics/histograms/metadata/geolocation/histograms.xml
@@ -105,15 +105,6 @@
   </summary>
 </histogram>
 
-<histogram name="Geolocation.NetworkLocationRequest.AccessPoints" units="units"
-    expires_after="M85">
-  <owner>mattreynolds@chromium.org</owner>
-  <owner>device-dev@chromium.org</owner>
-  <summary>
-    The number of WiFi access points used to determine geolocation.
-  </summary>
-</histogram>
-
 <histogram name="Geolocation.NetworkLocationRequest.Event"
     enum="NetworkLocationRequestEvent" expires_after="2024-04-28">
   <owner>mattreynolds@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml
index 1f1ca319..eedc75d 100644
--- a/tools/metrics/histograms/metadata/gpu/histograms.xml
+++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -1426,18 +1426,6 @@
   </summary>
 </histogram>
 
-<histogram name="GPU.SwapTimeUs" units="microseconds"
-    expires_after="2022-12-11">
-  <owner>vasilyt@chromium.org</owner>
-  <owner>backer@chromium.org</owner>
-  <summary>
-    This is logged once per frame if the output surface provides timing
-    information. It measures the time of SwapBuffers call. Only reported when
-    there is single surface swap in the same vsync interval. Only reported for
-    platforms supporting high resolution clocks.
-  </summary>
-</histogram>
-
 <histogram name="GPU.TransferCache.EntryFound" enum="BooleanYesNo"
     expires_after="2024-03-31">
   <owner>boliu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
index 702fcdb..2c8829649 100644
--- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -5321,13 +5321,6 @@
   <affected-histogram name="Media.Video.Roughness"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="VRSessionType" separator=".">
-  <suffix name="WebVR"
-      label="The session is restricted to the period that browser is
-             displaying WebVR contents."/>
-  <affected-histogram name="VRSessionTime"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="WebAppContainerEngagementType" separator=".">
   <suffix name="InTab" label="Happened in app running as a tab"/>
   <suffix name="InWindow" label="Happened in app running as a window"/>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml
index f6853f25..098ebe4 100644
--- a/tools/metrics/histograms/metadata/media/histograms.xml
+++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -2440,7 +2440,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageDatabaseSQLiteError"
-    enum="SqliteLoggedResultCode" expires_after="2024-08-11">
+    enum="SqliteLoggedResultCode" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2450,7 +2450,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageDatabaseSQLiteError.ClearDatabase"
-    enum="SqliteLoggedResultCode" expires_after="2023-12-19">
+    enum="SqliteLoggedResultCode" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2460,7 +2460,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageDatabaseSQLiteError.DeleteFile"
-    enum="SqliteLoggedResultCode" expires_after="2023-12-19">
+    enum="SqliteLoggedResultCode" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2471,7 +2471,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageDatabaseSQLiteError.DeleteForStorageKey"
-    enum="SqliteLoggedResultCode" expires_after="2023-12-19">
+    enum="SqliteLoggedResultCode" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2482,7 +2482,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageDatabaseSQLiteError.OpenDatabase"
-    enum="SqliteLoggedResultCode" expires_after="2023-12-19">
+    enum="SqliteLoggedResultCode" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2492,7 +2492,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageDatabaseSQLiteError.ReadFile"
-    enum="SqliteLoggedResultCode" expires_after="2023-12-19">
+    enum="SqliteLoggedResultCode" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2503,7 +2503,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageDatabaseSQLiteError.WriteFile"
-    enum="SqliteLoggedResultCode" expires_after="2023-12-19">
+    enum="SqliteLoggedResultCode" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2514,7 +2514,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageManager.DatabaseOpenError"
-    enum="CdmStorageOpenError" expires_after="2024-08-11">
+    enum="CdmStorageOpenError" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2524,7 +2524,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageManager.DatabaseOpenError.{ProfileType}"
-    enum="CdmStorageOpenError" expires_after="2024-08-11">
+    enum="CdmStorageOpenError" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2539,7 +2539,7 @@
 
 <histogram
     name="Media.EME.CdmStorageManager.DatabaseOpenError.{ProfileType}.Migration"
-    enum="CdmStorageOpenError" expires_after="2024-08-11">
+    enum="CdmStorageOpenError" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2554,7 +2554,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageManager.DeleteDatabaseError.{ProfileType}"
-    enum="BooleanError" expires_after="2024-08-11">
+    enum="BooleanError" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2568,7 +2568,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageManager.DeleteFileError.{ProfileType}"
-    enum="BooleanError" expires_after="2024-08-11">
+    enum="BooleanError" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2583,7 +2583,7 @@
 
 <histogram
     name="Media.EME.CdmStorageManager.DeleteFileError.{ProfileType}.Migration"
-    enum="BooleanError" expires_after="2024-08-11">
+    enum="BooleanError" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2599,7 +2599,7 @@
 
 <histogram
     name="Media.EME.CdmStorageManager.DeleteForStorageKeyError.{ProfileType}"
-    enum="BooleanError" expires_after="2024-08-11">
+    enum="BooleanError" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2613,7 +2613,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageManager.ReadFileError.{ProfileType}"
-    enum="BooleanError" expires_after="2024-08-11">
+    enum="BooleanError" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2628,7 +2628,7 @@
 
 <histogram
     name="Media.EME.CdmStorageManager.ReadFileError.{ProfileType}.Migration"
-    enum="BooleanError" expires_after="2024-08-11">
+    enum="BooleanError" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2643,7 +2643,7 @@
 </histogram>
 
 <histogram name="Media.EME.CdmStorageManager.WriteFileError.{ProfileType}"
-    enum="BooleanError" expires_after="2024-08-11">
+    enum="BooleanError" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -2658,7 +2658,7 @@
 
 <histogram
     name="Media.EME.CdmStorageManager.WriteFileError.{ProfileType}.Migration"
-    enum="BooleanError" expires_after="2024-08-11">
+    enum="BooleanError" expires_after="2024-04-11">
   <owner>vpasupathy@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/navigation/enums.xml b/tools/metrics/histograms/metadata/navigation/enums.xml
new file mode 100644
index 0000000..73041fd
--- /dev/null
+++ b/tools/metrics/histograms/metadata/navigation/enums.xml
@@ -0,0 +1,43 @@
+<!--
+Copyright 2023 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+
+This file describes the enumerations referenced by entries in histograms.xml for
+this directory. Some enums may instead be listed in the central enums.xml file
+at src/tools/metrics/histograms/enums.xml when multiple files use them.
+
+For best practices on writing enumerations descriptions, see
+https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md#Enum-Histograms
+
+Please follow the instructions in the OWNERS file in this directory to find a
+reviewer. If no OWNERS file exists, please consider signing up at
+go/reviewing-metrics (Googlers only), as all subdirectories are expected to
+have an OWNERS file. As a last resort you can send the CL to
+chromium-metrics-reviews@google.com.
+-->
+
+<histogram-configuration>
+
+<!-- Enum types -->
+
+<enums>
+
+<enum name="AutomaticBeaconOutcome">
+  <int value="0" label="Success"/>
+  <int value="1" label="No transient user activation"/>
+  <int value="2" label="Initiator frame not same-origin with mapped URL"/>
+</enum>
+
+<enum name="FencedFrameAutomaticBeaconEventType">
+  <int value="0" label="reserved.top_navigation"/>
+  <int value="1" label="reserved.top_navigation_start"/>
+  <int value="2" label="reserved.top_navigation_commit"/>
+</enum>
+
+</enums>
+
+</histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml
index 7829081..3a15ecd 100644
--- a/tools/metrics/histograms/metadata/navigation/histograms.xml
+++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -483,6 +483,7 @@
     enum="AutomaticBeaconOutcome" expires_after="2024-10-01">
   <owner>lbrady@google.com</owner>
   <owner>shivanisha@chromium.org</owner>
+  <owner>chrome-fenced-frames-core@google.com</owner>
   <summary>
     Record if a 'reserved.top_navigation' automatic beacon was sent out, or the
     reason for not sending the beacon if it was not sent out.
@@ -695,10 +696,22 @@
   </summary>
 </histogram>
 
+<histogram name="Navigation.FencedFrameAutomaticBeaconEventType"
+    enum="FencedFrameAutomaticBeaconEventType" expires_after="2024-10-01">
+  <owner>lbrady@google.com</owner>
+  <owner>shivanisha@chromium.org</owner>
+  <owner>chrome-fenced-frames-core@google.com</owner>
+  <summary>
+    Recorded what event type is used when automatic beacon data is set using
+    setReportEventDataForAutomaticBeacons().
+  </summary>
+</histogram>
+
 <histogram name="Navigation.FencedFrameTopNavigation"
     enum="FencedFrameNavigationState" expires_after="2024-10-01">
   <owner>lbrady@google.com</owner>
   <owner>shivanisha@chromium.org</owner>
+  <owner>chrome-fenced-frames-core@google.com</owner>
   <summary>
     This records top-level navigations that originated from a fenced frame or
     URN iframe. At navigation start, a 'Begin' is logged. If the navigation
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml
index 89ff331..b07ccab 100644
--- a/tools/metrics/histograms/metadata/password/histograms.xml
+++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -891,7 +891,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BiometricAuthPwdFill.AuthResult"
-    enum="DeviceAuthFinalResult" expires_after="2023-12-04">
+    enum="DeviceAuthFinalResult" expires_after="2024-10-28">
   <owner>ioanap@chromium.org</owner>
   <owner>fhorschig@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/permissions/histograms.xml b/tools/metrics/histograms/metadata/permissions/histograms.xml
index 4dc5172..834698a 100644
--- a/tools/metrics/histograms/metadata/permissions/histograms.xml
+++ b/tools/metrics/histograms/metadata/permissions/histograms.xml
@@ -416,10 +416,6 @@
 
 <histogram name="Permissions.CrowdDeny.PreloadData.WarningOnly" enum="Boolean"
     expires_after="2021-10-25">
-  <obsolete>
-    Adding the obsolete tag for bookkeeping. Histogram not recorded since its
-    expiry date 2021-10-25
-  </obsolete>
   <owner>andypaicu@chromium.org</owner>
   <owner>engedy@chromium.org</owner>
   <owner>hkamila@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/sb_client/histograms.xml b/tools/metrics/histograms/metadata/sb_client/histograms.xml
index 81c24dd0..54743af 100644
--- a/tools/metrics/histograms/metadata/sb_client/histograms.xml
+++ b/tools/metrics/histograms/metadata/sb_client/histograms.xml
@@ -816,25 +816,6 @@
   </summary>
 </histogram>
 
-<histogram name="SBClientPhishing.TfLiteModelLoadTime.{Scorer}" units="ms"
-    expires_after="2022-03-16">
-  <obsolete>
-    Removed 03-2023 since the value was consistently small, and we don't expect
-    it to change over time.
-  </obsolete>
-  <owner>drubery@chromium.org</owner>
-  <owner>chrome-counter-abuse-alerts@google.com</owner>
-  <summary>
-    Records how long it takes the {Scorer} to load the TfLite model file from
-    the memory mapped file into a string. This blocks the main thread, so we
-    need to ensure it is small.
-  </summary>
-  <token key="Scorer">
-    <variant name="FlatbufferScorer" summary="Flatbuffer scorer"/>
-    <variant name="ProtobufScorer" summary="Protobuf scorer"/>
-  </token>
-</histogram>
-
 <histogram name="SBClientPhishing.VisualFeaturesClearReason"
     enum="CanExtractVisualFeaturesResult" expires_after="2024-10-26">
   <owner>andysjlim@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index d89fe42..3c12dc65 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -2344,7 +2344,7 @@
 </histogram>
 
 <histogram name="Tabs.Tasks.TabAddedWithValidProposedPosition" units="boolean"
-    expires_after="2023-11-19">
+    expires_after="2024-05-19">
   <owner>ckitagawa@chromium.org</owner>
   <owner>fredmello@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/xr/histograms.xml b/tools/metrics/histograms/metadata/xr/histograms.xml
index c0abdd49..f0dd0488 100644
--- a/tools/metrics/histograms/metadata/xr/histograms.xml
+++ b/tools/metrics/histograms/metadata/xr/histograms.xml
@@ -22,12 +22,13 @@
 
 <histograms>
 
-<histogram name="VRSessionTime" units="ms" expires_after="2024-04-28">
+<histogram name="VRSessionTime.WebVR" units="ms" expires_after="2024-04-28">
   <owner>alcooper@chromium.org</owner>
   <owner>xr-dev@chromium.org</owner>
   <summary>
     The duration of the VR session. Logged when a new disjoint session has
-    begun, or when the session has ended in a non-continuable way.
+    begun, or when the session has ended in a non-continuable way. Restricted to
+    the period that the browser is displaying WebVR (XR) content.
   </summary>
 </histogram>
 
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 081a1a0..92efc00 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/v38.0/linux-arm64/trace_processor_shell"
         },
         "win": {
-            "hash": "8978c203752d8d636c410e7647ae6211b4367e9b",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/b3c02f9c677ffb13be0a52066c0819aedd733de8/trace_processor_shell.exe"
+            "hash": "2ce6cdf2914ba7993ab9861fc21ff25ecd648ba5",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/33063c9403c381f5411e1cddf8688a912529b4d9/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "bb52a6e014d9272dc4784b1678eee77075df1a86",
             "full_remote_path": "perfetto-luci-artifacts/v38.0/linux-arm/trace_processor_shell"
         },
         "mac": {
-            "hash": "7c40ffd7cb36d23bc5888373a64ee3c829d71a30",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/b3c02f9c677ffb13be0a52066c0819aedd733de8/trace_processor_shell"
+            "hash": "35f1232eeda4274ed95a723a914cb930c79514a0",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/33063c9403c381f5411e1cddf8688a912529b4d9/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "cc287491e9ff9fe2c4866e5574eaea04134895a0",
             "full_remote_path": "perfetto-luci-artifacts/v38.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "4003bb3222bbf10a872e241aedae8ce05992db91",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/8ba96658b6e52e7d1f644973e6e89aeb8e5d1bda/trace_processor_shell"
+            "hash": "6adf1d7c403c1f9e15ef17fc85aa002e42d0d2ed",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/33063c9403c381f5411e1cddf8688a912529b4d9/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/v8_context_snapshot/v8_context_snapshot.gni b/tools/v8_context_snapshot/v8_context_snapshot.gni
index 91ab392..6053baa 100644
--- a/tools/v8_context_snapshot/v8_context_snapshot.gni
+++ b/tools/v8_context_snapshot/v8_context_snapshot.gni
@@ -7,7 +7,7 @@
 # third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.{cpp|h}.
 # to speedup creating a V8 context and setting up around it.
 
-import("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/v8_target_cpu.gni")
 import("//v8/gni/v8.gni")
diff --git a/ui/android/java/src/org/chromium/ui/dragdrop/DropDataProviderUtils.java b/ui/android/java/src/org/chromium/ui/dragdrop/DropDataProviderUtils.java
index 31228bdd..be5c8d7 100644
--- a/ui/android/java/src/org/chromium/ui/dragdrop/DropDataProviderUtils.java
+++ b/ui/android/java/src/org/chromium/ui/dragdrop/DropDataProviderUtils.java
@@ -18,37 +18,36 @@
 /**
  * This class wraps all the calls to ContentResolver#call.
  *
- * TODO(https://crbug.com/1353048): Return a boolean with the result for each method.
  */
 public class DropDataProviderUtils {
     /**
      * Wraps the call to onDragEnd in the provider, we call it to clear the cached image data after
      * dragging ends
+     *
+     * @return Whether the image cache was successfully cleared.
      */
-    static void clearImageCache(boolean imageIsInUse) {
+    static boolean clearImageCache(boolean imageIsInUse) {
         Bundle bundle = new Bundle();
         bundle.putBoolean("imageIsInUse", imageIsInUse);
         try {
             ContextUtils.getApplicationContext().getContentResolver().call(
                     DropDataProviderImpl.FULL_AUTH_URI, ON_DRAG_END_METHOD_NAME, "", bundle);
+            return true;
         } catch (NullPointerException | IllegalArgumentException exception) {
-            // TODO(https://crbug.com/1353048): Return a boolean with the result to let the caller
-            // know.
+            return false;
         }
     }
 
-    /**
-     * Wraps the call to setClearCachedDataIntervalMs in the provider.
-     */
-    public static void setClearCachedDataIntervalMs(int delay) {
+    /** Wraps the call to setClearCachedDataIntervalMs in the provider. */
+    public static boolean setClearCachedDataIntervalMs(int delay) {
         Bundle bundle = new Bundle();
         bundle.putInt(DropDataProviderImpl.CLEAR_CACHE_PARAM, delay);
         try {
             ContextUtils.getApplicationContext().getContentResolver().call(
                     DropDataProviderImpl.FULL_AUTH_URI, SET_INTERVAL_METHOD_NAME, "", bundle);
+            return true;
         } catch (NullPointerException | IllegalArgumentException exception) {
-            // TODO(https://crbug.com/1353048): Return a boolean with the result to let the caller
-            // know.
+            return false;
         }
     }
 
@@ -69,8 +68,6 @@
                     DropDataProviderImpl.FULL_AUTH_URI, CACHE_METHOD_NAME, "", bundle);
             return cachedUriBundle.getParcelable("uri");
         } catch (NullPointerException | IllegalArgumentException exception) {
-            // TODO(https://crbug.com/1353048): Return a boolean with the result to let the caller
-            // know.
             return null;
         }
     }
diff --git a/ui/base/ime/ash/input_method_ash.cc b/ui/base/ime/ash/input_method_ash.cc
index b0d30f1..897accb 100644
--- a/ui/base/ime/ash/input_method_ash.cc
+++ b/ui/base/ime/ash/input_method_ash.cc
@@ -380,17 +380,6 @@
   }
 }
 
-void InputMethodAsh::OnTouch(ui::EventPointerType pointerType) {
-  TextInputClient* client = GetTextInputClient();
-  if (!client || !IsTextInputClientFocused(client)) {
-    return;
-  }
-  TextInputMethod* engine = GetEngine();
-  if (engine) {
-    engine->OnTouch(pointerType);
-  }
-}
-
 void InputMethodAsh::OnBlur() {
   if (IMEBridge::Get() && IMEBridge::Get()->GetInputContextHandler() == this) {
     IMEBridge::Get()->SetInputContextHandler(nullptr);
diff --git a/ui/base/ime/ash/input_method_ash.h b/ui/base/ime/ash/input_method_ash.h
index 7f2494ac..5f9a0ca 100644
--- a/ui/base/ime/ash/input_method_ash.h
+++ b/ui/base/ime/ash/input_method_ash.h
@@ -53,7 +53,6 @@
   // Overridden from InputMethodBase:
   void OnFocus() override;
   void OnBlur() override;
-  void OnTouch(ui::EventPointerType pointerType) override;
   void OnWillChangeFocusedClient(ui::TextInputClient* focused_before,
                                  ui::TextInputClient* focused) override;
   void OnDidChangeFocusedClient(ui::TextInputClient* focused_before,
diff --git a/ui/base/ime/ash/mock_ime_engine_handler.cc b/ui/base/ime/ash/mock_ime_engine_handler.cc
index d7a3f17..2254842 100644
--- a/ui/base/ime/ash/mock_ime_engine_handler.cc
+++ b/ui/base/ime/ash/mock_ime_engine_handler.cc
@@ -29,8 +29,6 @@
   last_text_input_context_.type = ui::TEXT_INPUT_TYPE_NONE;
 }
 
-void MockIMEEngineHandler::OnTouch(ui::EventPointerType pointerType) {}
-
 void MockIMEEngineHandler::Enable(const std::string& component_id) {
 }
 
diff --git a/ui/base/ime/ash/mock_ime_engine_handler.h b/ui/base/ime/ash/mock_ime_engine_handler.h
index 2731fe1e..8170e3e7 100644
--- a/ui/base/ime/ash/mock_ime_engine_handler.h
+++ b/ui/base/ime/ash/mock_ime_engine_handler.h
@@ -28,7 +28,6 @@
   // TextInputMethod:
   void Focus(const InputContext& input_context) override;
   void Blur() override;
-  void OnTouch(ui::EventPointerType pointerType) override;
   void Enable(const std::string& component_id) override;
   void Disable() override;
   void Reset() override;
diff --git a/ui/base/ime/ash/text_input_method.h b/ui/base/ime/ash/text_input_method.h
index 26c47076..89a6c8d 100644
--- a/ui/base/ime/ash/text_input_method.h
+++ b/ui/base/ime/ash/text_input_method.h
@@ -110,9 +110,6 @@
   // Informs the input method that focus has been lost.
   virtual void Blur() = 0;
 
-  // Called on touch inside an input field which already has focus.
-  virtual void OnTouch(ui::EventPointerType pointerType) = 0;
-
   // Called when the IME is enabled.
   virtual void Enable(const std::string& component_id) = 0;
 
diff --git a/ui/base/ime/dummy_input_method.cc b/ui/base/ime/dummy_input_method.cc
index b7ac539..2103caf 100644
--- a/ui/base/ime/dummy_input_method.cc
+++ b/ui/base/ime/dummy_input_method.cc
@@ -20,8 +20,6 @@
 void DummyInputMethod::OnFocus() {
 }
 
-void DummyInputMethod::OnTouch(ui::EventPointerType pointerType) {}
-
 void DummyInputMethod::OnBlur() {
 }
 
diff --git a/ui/base/ime/dummy_input_method.h b/ui/base/ime/dummy_input_method.h
index 4258a9b..d17ca73 100644
--- a/ui/base/ime/dummy_input_method.h
+++ b/ui/base/ime/dummy_input_method.h
@@ -25,7 +25,6 @@
   void SetImeKeyEventDispatcher(
       ImeKeyEventDispatcher* ime_key_event_dispatcher) override;
   void OnFocus() override;
-  void OnTouch(ui::EventPointerType pointerType) override;
   void OnBlur() override;
 
 #if BUILDFLAG(IS_WIN)
diff --git a/ui/base/ime/input_method.h b/ui/base/ime/input_method.h
index f178e0c..8252e245 100644
--- a/ui/base/ime/input_method.h
+++ b/ui/base/ime/input_method.h
@@ -63,9 +63,6 @@
   // Called when the top-level system window gets keyboard focus.
   virtual void OnFocus() = 0;
 
-  // Called when there is a touch within a text field that has focus.
-  virtual void OnTouch(ui::EventPointerType pointerType) = 0;
-
   // Called when the top-level system window loses keyboard focus.
   virtual void OnBlur() = 0;
 
diff --git a/ui/base/ime/input_method_base.cc b/ui/base/ime/input_method_base.cc
index bb429ca..a2e1a22 100644
--- a/ui/base/ime/input_method_base.cc
+++ b/ui/base/ime/input_method_base.cc
@@ -47,8 +47,6 @@
 void InputMethodBase::OnBlur() {
 }
 
-void InputMethodBase::OnTouch(ui::EventPointerType pointerType) {}
-
 void InputMethodBase::SetFocusedTextInputClient(TextInputClient* client) {
   SetFocusedTextInputClientInternal(client);
 }
diff --git a/ui/base/ime/input_method_base.h b/ui/base/ime/input_method_base.h
index 26f894de..8120710 100644
--- a/ui/base/ime/input_method_base.h
+++ b/ui/base/ime/input_method_base.h
@@ -42,7 +42,6 @@
   void SetImeKeyEventDispatcher(
       ImeKeyEventDispatcher* ime_key_event_dispatcher) override;
   void OnFocus() override;
-  void OnTouch(ui::EventPointerType pointerType) override;
   void OnBlur() override;
 
   void SetFocusedTextInputClient(TextInputClient* client) override;
diff --git a/ui/base/ime/mock_input_method.cc b/ui/base/ime/mock_input_method.cc
index 2b3b800..2f284a65 100644
--- a/ui/base/ime/mock_input_method.cc
+++ b/ui/base/ime/mock_input_method.cc
@@ -65,8 +65,6 @@
     observer.OnFocus();
 }
 
-void MockInputMethod::OnTouch(ui::EventPointerType pointerType) {}
-
 void MockInputMethod::OnBlur() {
   for (InputMethodObserver& observer : observer_list_)
     observer.OnBlur();
diff --git a/ui/base/ime/mock_input_method.h b/ui/base/ime/mock_input_method.h
index 36727e8..eb5e7e9 100644
--- a/ui/base/ime/mock_input_method.h
+++ b/ui/base/ime/mock_input_method.h
@@ -37,7 +37,6 @@
       ImeKeyEventDispatcher* ime_key_event_dispatcher) override;
   void OnFocus() override;
   void OnBlur() override;
-  void OnTouch(ui::EventPointerType pointerType) override;
 
 #if BUILDFLAG(IS_WIN)
   bool OnUntranslatedIMEMessage(const CHROME_MSG event,
diff --git a/ui/events/gestures/blink/BUILD.gn b/ui/events/gestures/blink/BUILD.gn
index 4a9291b3..0c392bb 100644
--- a/ui/events/gestures/blink/BUILD.gn
+++ b/ui/events/gestures/blink/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 
 source_set("blink") {
   sources = [
diff --git a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.ts b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.ts
index a54a2673..482ffeb 100644
--- a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.ts
+++ b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.ts
@@ -626,8 +626,7 @@
 
     // If this drag operation is initiated by mouse, check if we should start
     // selecting area.
-    // TODO: Remove `as FileGrid` once FileTableList is converted to TS.
-    if (!this.touching_ && (list as FileGrid).shouldStartDragSelection(event)) {
+    if (!this.touching_ && list.shouldStartDragSelection!(event)) {
       event.preventDefault();
       this.dragSelector_.startDragSelection(list, event);
       return;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table.js b/ui/file_manager/file_manager/foreground/js/ui/file_table.js
deleted file mode 100644
index c1816e1d..0000000
--- a/ui/file_manager/file_manager/foreground/js/ui/file_table.js
+++ /dev/null
@@ -1,1516 +0,0 @@
-// Copyright 2012 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {assert, assertInstanceof} from 'chrome://resources/ash/common/assert.js';
-import {dispatchSimpleEvent} from 'chrome://resources/ash/common/cr_deprecated.js';
-
-import {RateLimiter} from '../../../common/js/async_util.js';
-import {maybeShowTooltip} from '../../../common/js/dom_utils.js';
-import {entriesToURLs, isTeamDriveRoot} from '../../../common/js/entry_utils.js';
-import {FileType} from '../../../common/js/file_type.js';
-import {isDlpEnabled, isJellyEnabled} from '../../../common/js/flags.js';
-import {getEntryLabel, str, strf} from '../../../common/js/translations.js';
-import {FilesAppEntry} from '../../../externs/files_app_entry_interfaces.js';
-import {VolumeManager} from '../../../externs/volume_manager.js';
-import {FileListModel, GROUP_BY_FIELD_MODIFICATION_TIME} from '../file_list_model.js';
-import {ListThumbnailLoader} from '../list_thumbnail_loader.js';
-import {MetadataModel} from '../metadata/metadata_model.js';
-
-import {A11yAnnounce} from './a11y_announce.js';
-import {DragSelector} from './drag_selector.js';
-import {FileMetadataFormatter} from './file_metadata_formatter.js';
-import {decorateListItem, FileTableList, isDlpBlocked, renderFileNameLabel, renderFileTypeIcon, renderIconBadge, updateCacheItemInlineStatus, updateListItemExternalProps} from './file_table_list.js';
-import {Table} from './table/table.js';
-import {TableColumn} from './table/table_column.js';
-import {TableColumnModel} from './table/table_column_model.js';
-
-/**
- * Custom column model for advanced auto-resizing.
- */
-export class FileTableColumnModel extends TableColumnModel {
-  /**
-   * @param {!Array<TableColumn>} tableColumns Table columns.
-   */
-  constructor(tableColumns) {
-    super(tableColumns);
-
-    /** @private @type {?FileTableColumnModel.ColumnSnapshot} */
-    this.snapshot_ = null;
-  }
-
-  /**
-   * Sets column width so that the column dividers move to the specified
-   * position. This function also check the width of each column and keep the
-   * width larger than MIN_WIDTH_.
-   *
-   * @private
-   * @param {Array<number>} newPos Positions of each column dividers.
-   */
-  applyColumnPositions_(newPos) {
-    // Check the minimum width and adjust the positions.
-    for (let i = 0; i < newPos.length - 2; i++) {
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      if (!this.columns_[i].visible) {
-        // @ts-ignore: error TS2322: Type 'number | undefined' is not assignable
-        // to type 'number'.
-        newPos[i + 1] = newPos[i];
-        // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      } else if (newPos[i + 1] - newPos[i] < FileTableColumnModel.MIN_WIDTH_) {
-        // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-        newPos[i + 1] = newPos[i] + FileTableColumnModel.MIN_WIDTH_;
-      }
-    }
-    for (let i = newPos.length - 1; i >= 2; i--) {
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      if (!this.columns_[i - 1].visible) {
-        // @ts-ignore: error TS2322: Type 'number | undefined' is not assignable
-        // to type 'number'.
-        newPos[i - 1] = newPos[i];
-        // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      } else if (newPos[i] - newPos[i - 1] < FileTableColumnModel.MIN_WIDTH_) {
-        // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-        newPos[i - 1] = newPos[i] - FileTableColumnModel.MIN_WIDTH_;
-      }
-    }
-    // Set the new width of columns
-    for (let i = 0; i < this.columns_.length; i++) {
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      if (!this.columns_[i].visible) {
-        // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-        this.columns_[i].width = 0;
-      } else {
-        // Make sure each cell has the minimum width. This is necessary when the
-        // window size is too small to contain all the columns.
-        // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-        this.columns_[i].width = Math.max(
-            // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-            FileTableColumnModel.MIN_WIDTH_, newPos[i + 1] - newPos[i]);
-      }
-    }
-  }
-
-  /**
-   * Normalizes widths to make their sum 100% if possible. Uses the proportional
-   * approach with some additional constraints.
-   *
-   * @param {number} contentWidth Target width.
-   * @override
-   */
-  normalizeWidths(contentWidth) {
-    let totalWidth = 0;
-    // Some columns have fixed width.
-    for (let i = 0; i < this.columns_.length; i++) {
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      totalWidth += this.columns_[i].width;
-    }
-    const positions = [0];
-    let sum = 0;
-    for (let i = 0; i < this.columns_.length; i++) {
-      const column = this.columns_[i];
-      // @ts-ignore: error TS18048: 'column' is possibly 'undefined'.
-      sum += column.width;
-      // Faster alternative to Math.floor for non-negative numbers.
-      positions[i + 1] = ~~(contentWidth * sum / totalWidth);
-    }
-    this.applyColumnPositions_(positions);
-  }
-
-  /**
-   * Handles to the start of column resizing by splitters.
-   */
-  handleSplitterDragStart() {
-    this.initializeColumnPos();
-  }
-
-  /**
-   * Handles to the end of column resizing by splitters.
-   */
-  handleSplitterDragEnd() {
-    this.destroyColumnPos();
-  }
-
-  /**
-   * Initialize a column snapshot which is used in setWidthAndKeepTotal().
-   */
-  initializeColumnPos() {
-    this.snapshot_ = new FileTableColumnModel.ColumnSnapshot(this.columns_);
-  }
-
-  /**
-   * Destroy the column snapshot which is used in setWidthAndKeepTotal().
-   */
-  destroyColumnPos() {
-    this.snapshot_ = null;
-  }
-
-  /**
-   * Sets the width of column while keeping the total width of table.
-   * Before and after calling this method, you must initialize and destroy
-   * columnPos with initializeColumnPos() and destroyColumnPos().
-   * @param {number} columnIndex Index of column that is resized.
-   * @param {number} columnWidth New width of the column.
-   */
-  setWidthAndKeepTotal(columnIndex, columnWidth) {
-    columnWidth = Math.max(columnWidth, FileTableColumnModel.MIN_WIDTH_);
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    this.snapshot_.setWidth(columnIndex, columnWidth);
-    // @ts-ignore: error TS2341: Property 'newPos' is private and only
-    // accessible within class 'ColumnSnapshot'.
-    this.applyColumnPositions_(this.snapshot_.newPos);
-
-    // Notify about resizing
-    dispatchSimpleEvent(this, 'resize');
-  }
-
-  /**
-   * Obtains a column by the specified horizontal position.
-   * @param {number} x Horizontal position.
-   * @return {Object} The object that contains column index, column width, and
-   *     hitPosition where the horizontal position is hit in the column.
-   */
-  getHitColumn(x) {
-    let i = 0;
-    // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-    for (; i < this.columns_.length && x >= this.columns_[i].width; i++) {
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      x -= this.columns_[i].width;
-    }
-    if (i >= this.columns_.length) {
-      // @ts-ignore: error TS2322: Type 'null' is not assignable to type
-      // 'Object'.
-      return null;
-    }
-    // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-    return {index: i, hitPosition: x, width: this.columns_[i].width};
-  }
-
-  /** @override */
-  // @ts-ignore: error TS7006: Parameter 'visible' implicitly has an 'any' type.
-  setVisible(index, visible) {
-    if (index < 0 || index > this.columns_.length - 1) {
-      return;
-    }
-
-    const column = this.columns_[index];
-    // @ts-ignore: error TS18048: 'column' is possibly 'undefined'.
-    if (column.visible === visible) {
-      return;
-    }
-
-    // Re-layout the table.  This overrides the default column layout code in
-    // the parent class.
-    const snapshot = new FileTableColumnModel.ColumnSnapshot(this.columns_);
-
-    // @ts-ignore: error TS18048: 'column' is possibly 'undefined'.
-    column.visible = visible;
-
-    // Keep the current column width, but adjust the other columns to
-    // accommodate the new column.
-    // @ts-ignore: error TS18048: 'column' is possibly 'undefined'.
-    snapshot.setWidth(index, column.width);
-    // @ts-ignore: error TS2341: Property 'newPos' is private and only
-    // accessible within class 'ColumnSnapshot'.
-    this.applyColumnPositions_(snapshot.newPos);
-  }
-
-  /**
-   * Export a set of column widths for use by #restoreColumnWidths.  Use these
-   * two methods instead of manually saving and setting column widths, because
-   * doing the latter will not correctly save/restore column widths for hidden
-   * columns.
-   * see #restoreColumnWidths
-   * @return {!Object} config
-   */
-  exportColumnConfig() {
-    // Make a snapshot, and use that to compute a column layout where all the
-    // columns are visible.
-    const snapshot = new FileTableColumnModel.ColumnSnapshot(this.columns_);
-    for (let i = 0; i < this.columns_.length; i++) {
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      if (!this.columns_[i].visible) {
-        // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-        snapshot.setWidth(i, this.columns_[i].absoluteWidth);
-      }
-    }
-    // Export the column widths.
-    const config = {};
-    for (let i = 0; i < this.columns_.length; i++) {
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      config[this.columns_[i].id] = {
-        // @ts-ignore: error TS2341: Property 'newPos' is private and only
-        // accessible within class 'ColumnSnapshot'.
-        width: snapshot.newPos[i + 1] - snapshot.newPos[i],
-      };
-    }
-    return config;
-  }
-
-  /**
-   * Restores a set of column widths previously created by calling
-   * #exportColumnConfig.
-   * see #exportColumnConfig
-   * @param {!Object} config
-   */
-  restoreColumnConfig(config) {
-    // Convert old-style raw column widths into new-style config objects.
-    if (Array.isArray(config)) {
-      const tmpConfig = {};
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      tmpConfig[this.columns_[0].id] = config[0];
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      tmpConfig[this.columns_[1].id] = config[1];
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      tmpConfig[this.columns_[3].id] = config[2];
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      tmpConfig[this.columns_[4].id] = config[3];
-      config = tmpConfig;
-    }
-
-    // Columns must all be made visible before restoring their widths.  Save the
-    // current visibility so it can be restored after.
-    const visibility = [];
-    for (let i = 0; i < this.columns_.length; i++) {
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      visibility[i] = this.columns_[i].visible;
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      this.columns_[i].visible = true;
-    }
-
-    // Do not use external setters (e.g. #setVisible, #setWidth) here because
-    // they trigger layout thrash, and also try to dynamically resize columns,
-    // which interferes with restoring the old column layout.
-    for (const columnId in config) {
-      const column = this.columns_[this.indexOf(columnId)];
-      if (column) {
-        // Set column width.  Ignore invalid widths.
-        // @ts-ignore: error TS7053: Element implicitly has an 'any' type
-        // because expression of type 'string' can't be used to index type
-        // 'Object'.
-        const width = ~~config[columnId].width;
-        if (width > 0) {
-          column.width = width;
-        }
-      }
-    }
-
-    // Restore column visibility.  Use setVisible here, to trigger table
-    // relayout.
-    for (let i = 0; i < this.columns_.length; i++) {
-      this.setVisible(i, visibility[i]);
-    }
-  }
-}
-
-/**
- * Customize the column header to decorate with a11y attributes that announces
- * the sorting used when clicked.
- *
- * @this {TableColumn} Bound by TableHeader before
- * calling.
- * @param {Element} table Table being rendered.
- * @return {Element}
- */
-export function renderHeader_(table) {
-  const column = /** @type {TableColumn} */ (this);
-  const container = table.ownerDocument.createElement('div');
-  container.classList.add('table-label-container');
-
-  const textElement = table.ownerDocument.createElement('span');
-  textElement.setAttribute('id', `column-${column.id}`);
-  textElement.textContent = column.name;
-  // @ts-ignore: error TS2339: Property 'dataModel' does not exist on type
-  // 'Element'.
-  const dm = table.dataModel;
-
-  let sortOrder = column.defaultOrder;
-  let isSorted = false;
-  if (dm && dm.sortStatus.field === column.id) {
-    isSorted = true;
-    // Here we have to flip, because clicking will perform the opposite sorting.
-    sortOrder = dm.sortStatus.direction === 'desc' ? 'asc' : 'desc';
-  }
-
-  textElement.setAttribute('aria-describedby', 'sort-column-' + sortOrder);
-  textElement.setAttribute('role', 'button');
-  container.appendChild(textElement);
-
-  const icon = document.createElement('cr-icon-button');
-  const iconName = sortOrder === 'desc' ? 'up' : 'down';
-  icon.setAttribute('iron-icon', `files16:arrow_${iconName}_small`);
-  // If we're the sorting column make the icon a tab target.
-  if (isSorted) {
-    icon.id = 'sort-direction-button';
-    icon.setAttribute('tabindex', '0');
-    icon.setAttribute('aria-hidden', 'false');
-    if (sortOrder === 'asc') {
-      icon.setAttribute('aria-label', str('COLUMN_ASC_SORT_MESSAGE'));
-    } else {
-      icon.setAttribute('aria-label', str('COLUMN_DESC_SORT_MESSAGE'));
-    }
-  } else {
-    icon.setAttribute('tabindex', '-1');
-    icon.setAttribute('aria-hidden', 'true');
-  }
-  icon.classList.add('sort-icon', 'no-overlap');
-
-  container.classList.toggle('not-sorted', !isSorted);
-  container.classList.toggle('sorted', isSorted);
-
-  container.appendChild(icon);
-
-  return container;
-}
-
-/**
- * Minimum width of column. Note that is not marked private as it is used in the
- * unit tests.
- * @const @type {number}
- */
-FileTableColumnModel.MIN_WIDTH_ = 40;
-
-/**
- * A helper class for performing resizing of columns.
- */
-FileTableColumnModel.ColumnSnapshot = class {
-  /**
-   * @param {!Array<!TableColumn>} columns
-   */
-  constructor(columns) {
-    /** @private @type {!Array<number>} */
-    this.columnPos_ = [0];
-    for (let i = 0; i < columns.length; i++) {
-      // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-      this.columnPos_[i + 1] = columns[i].width + this.columnPos_[i];
-    }
-
-    /**
-     * Starts off as a copy of the current column positions, but gets modified.
-     * @private @type {!Array<number>}
-     */
-    this.newPos = this.columnPos_.slice(0);
-  }
-
-  /**
-   * Set the width of the given column.  The snapshot will keep the total width
-   * of the table constant.
-   * @param {number} index
-   * @param {number} width
-   */
-  setWidth(index, width) {
-    // Skip to resize 'selection' column
-    if (index < 0 || index >= this.columnPos_.length - 1 || !this.columnPos_) {
-      return;
-    }
-
-    // Round up if the column is shrinking, and down if the column is expanding.
-    // This prevents off-by-one drift.
-    // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-    const currentWidth = this.columnPos_[index + 1] - this.columnPos_[index];
-    const round = width < currentWidth ? Math.ceil : Math.floor;
-
-    // Calculate new positions of column splitters.
-    // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-    const newPosStart = this.columnPos_[index] + width;
-    const posEnd = this.columnPos_[this.columnPos_.length - 1];
-    for (let i = 0; i < index + 1; i++) {
-      // @ts-ignore: error TS2322: Type 'number | undefined' is not assignable
-      // to type 'number'.
-      this.newPos[i] = this.columnPos_[i];
-    }
-    for (let i = index + 1; i < this.columnPos_.length - 1; i++) {
-      const posStart = this.columnPos_[index + 1];
-      // @ts-ignore: error TS18048: 'posEnd' is possibly 'undefined'.
-      this.newPos[i] = (posEnd - newPosStart) *
-              // @ts-ignore: error TS18048: 'posStart' is possibly 'undefined'.
-              (this.columnPos_[i] - posStart) / (posEnd - posStart) +
-          newPosStart;
-      // @ts-ignore: error TS2345: Argument of type 'number | undefined' is not
-      // assignable to parameter of type 'number'.
-      this.newPos[i] = round(this.newPos[i]);
-    }
-    // @ts-ignore: error TS2322: Type 'number | undefined' is not assignable to
-    // type 'number'.
-    this.newPos[index] = this.columnPos_[index];
-    // @ts-ignore: error TS2322: Type 'number | undefined' is not assignable to
-    // type 'number'.
-    this.newPos[this.columnPos_.length - 1] = posEnd;
-  }
-};
-
-/**
- * File list Table View.
- */
-// @ts-ignore: error TS2415: Class 'FileTable' incorrectly extends base class
-// 'Table'.
-export class FileTable extends Table {
-  constructor() {
-    super();
-
-    /** @private @type {number} */
-    this.beginIndex_ = 0;
-
-    /** @private @type {number} */
-    this.endIndex_ = 0;
-
-    /** @private @type {?ListThumbnailLoader} */
-    this.listThumbnailLoader_ = null;
-
-    /** @private @type {?RateLimiter} */
-    this.relayoutRateLimiter_ = null;
-
-    /** @private @type {?MetadataModel} */
-    this.metadataModel_ = null;
-
-    /** @private @type {?FileMetadataFormatter} */
-    this.formatter_ = null;
-
-    /** @private @type {boolean} */
-    this.useModificationByMeTime_ = false;
-
-    /** @private @type {?VolumeManager} */
-    this.volumeManager_ = null;
-
-    // @ts-ignore: error TS2314: Generic type 'Array<T>' requires 1 type
-    // argument(s).
-    /** @private @type {!Array} */
-    this.lastSelection_ = [];
-
-    // @ts-ignore: error TS7014: Function type, which lacks return-type
-    // annotation, implicitly has an 'any' return type.
-    /** @private @type {?function(!Event)} */
-    this.onThumbnailLoadedBound_ = null;
-
-    /** @public @type {?A11yAnnounce} */
-    this.a11y = null;
-
-    throw new Error('Designed to decorate elements');
-  }
-
-  /**
-   * Decorates the element.
-   * @param {!Element} self Table to decorate.
-   * @param {!MetadataModel} metadataModel To retrieve metadata.
-   * @param {!VolumeManager} volumeManager To retrieve volume info.
-   * @param {!A11yAnnounce} a11y FileManagerUI to be able to announce a11y
-   *     messages.
-   * @param {boolean} fullPage True if it's full page File Manager, False if a
-   *    file open/save dialog.
-   * @suppress {checkPrototypalTypes} Closure was failing because the signature
-   * of this decorate() doesn't match the base class.
-   */
-  // @ts-ignore: error TS4119: This member must have a JSDoc comment with an
-  // '@override' tag because it overrides a member in the base class 'Table'.
-  static decorate(self, metadataModel, volumeManager, a11y, fullPage) {
-    Table.decorate(self);
-    // @ts-ignore: error TS2339: Property '__proto__' does not exist on type
-    // 'Element'.
-    self.__proto__ = FileTable.prototype;
-    // @ts-ignore: error TS2339: Property 'list' does not exist on type
-    // 'Element'.
-    FileTableList.decorate(self.list);
-    // @ts-ignore: error TS2339: Property 'updateHighPriorityRange_' does not
-    // exist on type 'Element'.
-    self.list.setOnMergeItems(self.updateHighPriorityRange_.bind(self));
-    // @ts-ignore: error TS2339: Property 'metadataModel_' does not exist on
-    // type 'Element'.
-    self.metadataModel_ = metadataModel;
-    // @ts-ignore: error TS2339: Property 'volumeManager_' does not exist on
-    // type 'Element'.
-    self.volumeManager_ = volumeManager;
-    // @ts-ignore: error TS2339: Property 'a11y' does not exist on type
-    // 'Element'.
-    self.a11y = a11y;
-
-    // Force the list's ending spacer to be tall enough to allow overscroll.
-    const endSpacer = self.querySelector('.spacer:last-child');
-    if (endSpacer) {
-      endSpacer.classList.add('signals-overscroll');
-    }
-
-    /** @private @type {ListThumbnailLoader} */
-    // @ts-ignore: error TS2339: Property 'listThumbnailLoader_' does not exist
-    // on type 'Element'.
-    self.listThumbnailLoader_ = null;
-
-    /** @private @type {number} */
-    // @ts-ignore: error TS2339: Property 'beginIndex_' does not exist on type
-    // 'Element'.
-    self.beginIndex_ = 0;
-
-    /** @private @type {number} */
-    // @ts-ignore: error TS2339: Property 'endIndex_' does not exist on type
-    // 'Element'.
-    self.endIndex_ = 0;
-
-    // @ts-ignore: error TS7014: Function type, which lacks return-type
-    // annotation, implicitly has an 'any' return type.
-    /** @private @type {function(!Event)} */
-    // @ts-ignore: error TS2339: Property 'onThumbnailLoaded_' does not exist on
-    // type 'Element'.
-    self.onThumbnailLoadedBound_ = self.onThumbnailLoaded_.bind(self);
-
-    /** @private @type {boolean} */
-    // @ts-ignore: error TS2339: Property 'useModificationByMeTime_' does not
-    // exist on type 'Element'.
-    self.useModificationByMeTime_ = false;
-
-    const nameColumn =
-        new TableColumn('name', str('NAME_COLUMN_LABEL'), fullPage ? 386 : 324);
-    // @ts-ignore: error TS2339: Property 'renderName_' does not exist on type
-    // 'Element'.
-    nameColumn.renderFunction = self.renderName_.bind(self);
-    nameColumn.headerRenderFunction = renderHeader_;
-
-    const sizeColumn = new TableColumn(
-        'size', str('SIZE_COLUMN_LABEL'), 110, isJellyEnabled() ? false : true);
-    // @ts-ignore: error TS2339: Property 'renderSize_' does not exist on type
-    // 'Element'.
-    sizeColumn.renderFunction = self.renderSize_.bind(self);
-    sizeColumn.defaultOrder = 'desc';
-    sizeColumn.headerRenderFunction = renderHeader_;
-
-    const typeColumn =
-        new TableColumn('type', str('TYPE_COLUMN_LABEL'), fullPage ? 110 : 110);
-    // @ts-ignore: error TS2339: Property 'renderType_' does not exist on type
-    // 'Element'.
-    typeColumn.renderFunction = self.renderType_.bind(self);
-    typeColumn.headerRenderFunction = renderHeader_;
-
-    const modTimeColumn = new TableColumn(
-        'modificationTime', str('DATE_COLUMN_LABEL'), fullPage ? 150 : 210);
-    // @ts-ignore: error TS2339: Property 'renderDate_' does not exist on type
-    // 'Element'.
-    modTimeColumn.renderFunction = self.renderDate_.bind(self);
-    modTimeColumn.defaultOrder = 'desc';
-    modTimeColumn.headerRenderFunction = renderHeader_;
-
-    const columns = [nameColumn, sizeColumn, typeColumn, modTimeColumn];
-
-    const columnModel = new FileTableColumnModel(columns);
-
-    // @ts-ignore: error TS2339: Property 'columnModel' does not exist on type
-    // 'Element'.
-    self.columnModel = columnModel;
-
-    // @ts-ignore: error TS2339: Property 'formatter_' does not exist on type
-    // 'Element'.
-    self.formatter_ = new FileMetadataFormatter();
-
-    // @ts-ignore: error TS2352: Conversion of type 'Element' to type 'Table'
-    // may be a mistake because neither type sufficiently overlaps with the
-    // other. If this was intentional, convert the expression to 'unknown'
-    // first.
-    const selfAsTable = /** @type {!Table} */ (self);
-    selfAsTable.setRenderFunction(
-        // @ts-ignore: error TS2339: Property 'renderTableRow_' does not exist
-        // on type 'Element'.
-        self.renderTableRow_.bind(self, selfAsTable.getRenderFunction()));
-
-    // Keep focus on the file list when clicking on the header.
-    selfAsTable.header.addEventListener('mousedown', e => {
-      // @ts-ignore: error TS2339: Property 'list' does not exist on type
-      // 'Element'.
-      self.list.focus();
-      e.preventDefault();
-    });
-
-    // @ts-ignore: error TS2339: Property 'relayoutRateLimiter_' does not exist
-    // on type 'Element'.
-    self.relayoutRateLimiter_ =
-        // @ts-ignore: error TS2339: Property 'relayoutImmediately_' does not
-        // exist on type 'Element'.
-        new RateLimiter(self.relayoutImmediately_.bind(self));
-
-    // Save the last selection. This is used by shouldStartDragSelection.
-    // @ts-ignore: error TS7006: Parameter 'e' implicitly has an 'any' type.
-    self.list.addEventListener('mousedown', function(e) {
-      // @ts-ignore: error TS2339: Property 'selectionModel' does not exist on
-      // type '(Anonymous function)'.
-      this.lastSelection_ = this.selectionModel.selectedIndexes;
-    }.bind(self), true);
-    // @ts-ignore: error TS7006: Parameter 'e' implicitly has an 'any' type.
-    self.list.addEventListener('touchstart', function(e) {
-      // @ts-ignore: error TS2339: Property 'selectionModel' does not exist on
-      // type '(Anonymous function)'.
-      this.lastSelection_ = this.selectionModel.selectedIndexes;
-    }.bind(self), true);
-    // @ts-ignore: error TS2339: Property 'list' does not exist on type
-    // 'Element'.
-    self.list.shouldStartDragSelection =
-        // @ts-ignore: error TS2339: Property 'shouldStartDragSelection_' does
-        // not exist on type 'Element'.
-        self.shouldStartDragSelection_.bind(self);
-
-    // @ts-ignore: error TS2339: Property 'list' does not exist on type
-    // 'Element'.
-    self.list.addEventListener(
-        // @ts-ignore: error TS2339: Property 'onMouseOver_' does not exist on
-        // type 'Element'.
-        'mouseover', self.onMouseOver_.bind(self), {passive: true});
-
-    // Update the item's inline status when it's restored from List's cache.
-    // @ts-ignore: error TS2339: Property 'list' does not exist on type
-    // 'Element'.
-    self.list.addEventListener(
-        'cachedItemRestored',
-        // @ts-ignore: error TS7006: Parameter 'e' implicitly has an 'any' type.
-        (e) => updateCacheItemInlineStatus(
-            // @ts-ignore: error TS2339: Property 'metadataModel_' does not
-            // exist on type 'Element'.
-            e.detail, self.dataModel, self.metadataModel_));
-  }
-
-  // @ts-ignore: error TS7006: Parameter 'event' implicitly has an 'any' type.
-  onMouseOver_(event) {
-    this.maybeShowToolTip(event);
-  }
-
-  // @ts-ignore: error TS7006: Parameter 'event' implicitly has an 'any' type.
-  maybeShowToolTip(event) {
-    const target = event.composedPath()[0];
-    if (!target) {
-      return;
-    }
-    if (!target.classList.contains('detail-name')) {
-      return;
-    }
-    const labelElement = target.querySelector('.filename-label');
-    if (!labelElement) {
-      return;
-    }
-
-    maybeShowTooltip(labelElement, labelElement.innerText);
-  }
-
-  /**
-   * Sort data by the given column. Overridden to add the a11y message after
-   * sorting.
-   * @param {number} index The index of the column to sort by.
-   * @override
-   */
-  sort(index) {
-    const cm = this.columnModel;
-    if (!this.dataModel) {
-      return;
-    }
-    const fieldName = cm.getId(index);
-    const sortStatus = this.dataModel.sortStatus;
-
-    let sortDirection = cm.getDefaultOrder(index);
-    // @ts-ignore: error TS2339: Property 'field' does not exist on type
-    // 'Object'.
-    if (sortStatus.field === fieldName) {
-      // If it's sorting the column that's already sorted, we need to flip the
-      // sorting order.
-      // @ts-ignore: error TS2339: Property 'direction' does not exist on type
-      // 'Object'.
-      sortDirection = sortStatus.direction === 'desc' ? 'asc' : 'desc';
-    }
-
-    const msgId =
-        sortDirection === 'asc' ? 'COLUMN_SORTED_ASC' : 'COLUMN_SORTED_DESC';
-    const msg = strf(msgId, fieldName);
-
-    // Delegate to parent to sort.
-    super.sort(index);
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    this.a11y.speakA11yMessage(msg);
-  }
-
-  /**
-   * @override
-   */
-  onDataModelSorted() {
-    const fileListModel = /** @type {FileListModel} */ (this.dataModel);
-    const hasGroupHeadingAfterSort = fileListModel.shouldShowGroupHeading();
-    // Sort doesn't trigger redraw sometimes, e.g. if we sort by Name for now,
-    // then we sort by time, if the list order doesn't change, no permuted event
-    // is triggered, thus no redraw is triggered. In this scenario, we need to
-    // manually trigger a redraw to remove/add the group heading.
-    if (hasGroupHeadingAfterSort !== fileListModel.hasGroupHeadingBeforeSort) {
-      // @ts-ignore: error TS2339: Property 'redraw' does not exist on type
-      // 'List'.
-      this.list.redraw();
-    }
-  }
-
-  /**
-   * Updates high priority range of list thumbnail loader based on current
-   * viewport.
-   *
-   * @param {number} beginIndex Begin index.
-   * @param {number} endIndex End index.
-   * @private
-   */
-  // @ts-ignore: error TS6133: 'updateHighPriorityRange_' is declared but its
-  // value is never read.
-  updateHighPriorityRange_(beginIndex, endIndex) {
-    // Keep these values to set range when a new list thumbnail loader is set.
-    this.beginIndex_ = beginIndex;
-    this.endIndex_ = endIndex;
-
-    if (this.listThumbnailLoader_ !== null) {
-      this.listThumbnailLoader_.setHighPriorityRange(beginIndex, endIndex);
-    }
-  }
-
-  /**
-   * Sets list thumbnail loader.
-   * @param {ListThumbnailLoader} listThumbnailLoader A list thumbnail loader.
-   */
-  setListThumbnailLoader(listThumbnailLoader) {
-    if (this.listThumbnailLoader_) {
-      this.listThumbnailLoader_.removeEventListener(
-          'thumbnailLoaded', this.onThumbnailLoadedBound_);
-    }
-
-    this.listThumbnailLoader_ = listThumbnailLoader;
-
-    if (this.listThumbnailLoader_) {
-      this.listThumbnailLoader_.addEventListener(
-          'thumbnailLoaded', this.onThumbnailLoadedBound_);
-      this.listThumbnailLoader_.setHighPriorityRange(
-          this.beginIndex_, this.endIndex_);
-    }
-  }
-
-  /**
-   * Returns the element containing the thumbnail of a certain list item as
-   * background image.
-   * @param {number} index The index of the item containing the desired
-   *     thumbnail.
-   * @return {?Element} The element containing the thumbnail, or null, if an
-   *     error occurred.
-   */
-  getThumbnail(index) {
-    const listItem = this.getListItemByIndex(index);
-    if (!listItem) {
-      return null;
-    }
-    const container = listItem.querySelector('.detail-thumbnail');
-    if (!container) {
-      return null;
-    }
-    return container.querySelector('.thumbnail');
-  }
-
-  /**
-   * Handles thumbnail loaded event.
-   * @param {!Event} event An event.
-   * @private
-   */
-  // @ts-ignore: error TS6133: 'onThumbnailLoaded_' is declared but its value is
-  // never read.
-  onThumbnailLoaded_(event) {
-    // @ts-ignore: error TS2339: Property 'index' does not exist on type
-    // 'Event'.
-    const listItem = this.getListItemByIndex(event.index);
-    if (listItem) {
-      const box = listItem.querySelector('.detail-thumbnail');
-      if (box) {
-        // @ts-ignore: error TS2339: Property 'dataUrl' does not exist on type
-        // 'Event'.
-        if (event.dataUrl) {
-          this.setThumbnailImage_(
-              // @ts-ignore: error TS2339: Property 'dataUrl' does not exist on
-              // type 'Event'.
-              assertInstanceof(box, HTMLDivElement), event.dataUrl);
-        } else {
-          this.clearThumbnailImage_(assertInstanceof(box, HTMLDivElement));
-        }
-        const icon = listItem.querySelector('.detail-icon');
-        // @ts-ignore: error TS2339: Property 'dataUrl' does not exist on type
-        // 'Event'.
-        icon.classList.toggle('has-thumbnail', !!event.dataUrl);
-      }
-    }
-  }
-
-  /**
-   * Adjust column width to fit its content.
-   * @param {number} index Index of the column to adjust width.
-   * @override
-   */
-  fitColumn(index) {
-    const render = this.columnModel.getRenderFunction(index);
-    const MAXIMUM_ROWS_TO_MEASURE = 1000;
-
-    // Create a temporaty list item, put all cells into it and measure its
-    // width. Then remove the item. It fits "list > *" CSS rules.
-    // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on type
-    // 'FileTable'.
-    const container = this.ownerDocument.createElement('li');
-    container.style.display = 'inline-block';
-    container.style.textAlign = 'start';
-    // The container will have width of the longest cell.
-    container.style.webkitBoxOrient = 'vertical';
-
-    // Select at most MAXIMUM_ROWS_TO_MEASURE items around visible area.
-    // @ts-ignore: error TS2339: Property 'getItemsInViewPort' does not exist on
-    // type 'List'.
-    const items = this.list.getItemsInViewPort(
-        this.list.scrollTop, this.list.clientHeight);
-    const firstIndex = Math.floor(
-        Math.max(0, (items.last + items.first - MAXIMUM_ROWS_TO_MEASURE) / 2));
-    const lastIndex =
-        Math.min(this.dataModel.length, firstIndex + MAXIMUM_ROWS_TO_MEASURE);
-    for (let i = firstIndex; i < lastIndex; i++) {
-      const item = this.dataModel.item(i);
-      // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-      // type 'FileTable'.
-      const div = this.ownerDocument.createElement('div');
-      div.className = 'table-row-cell';
-      // @ts-ignore: error TS2345: Argument of type 'this' is not assignable to
-      // parameter of type 'Element'.
-      div.appendChild(render(item, this.columnModel.getId(index), this));
-      container.appendChild(div);
-    }
-    this.list.appendChild(container);
-    const width = parseFloat(window.getComputedStyle(container).width);
-    this.list.removeChild(container);
-
-    // @ts-ignore: error TS2339: Property 'initializeColumnPos' does not exist
-    // on type 'TableColumnModel'.
-    this.columnModel.initializeColumnPos();
-    // @ts-ignore: error TS2339: Property 'setWidthAndKeepTotal' does not exist
-    // on type 'TableColumnModel'.
-    this.columnModel.setWidthAndKeepTotal(index, Math.ceil(width));
-    // @ts-ignore: error TS2339: Property 'destroyColumnPos' does not exist on
-    // type 'TableColumnModel'.
-    this.columnModel.destroyColumnPos();
-  }
-
-  /**
-   * Sets date and time format.
-   * @param {boolean} use12hourClock True if 12 hours clock, False if 24 hours.
-   */
-  setDateTimeFormat(use12hourClock) {
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    this.formatter_.setDateTimeFormat(use12hourClock);
-  }
-
-  /**
-   * Sets whether to use modificationByMeTime as "Last Modified" time.
-   * @param {boolean} useModificationByMeTime
-   */
-  setUseModificationByMeTime(useModificationByMeTime) {
-    this.useModificationByMeTime_ = useModificationByMeTime;
-  }
-
-  /**
-   * Obtains if the drag selection should be start or not by referring the mouse
-   * event.
-   * @param {MouseEvent} event Drag start event.
-   * @return {boolean} True if the mouse is hit to the background of the list,
-   * or certain areas of the inside of the list that would start a drag
-   * selection.
-   * @private
-   */
-  // @ts-ignore: error TS6133: 'shouldStartDragSelection_' is declared but its
-  // value is never read.
-  shouldStartDragSelection_(event) {
-    // If the shift key is pressed, it should starts drag selection.
-    if (event.shiftKey) {
-      return true;
-    }
-
-    // If we're outside of the element list, start the drag selection.
-    if (!/** @type {FileTableList} */ (this.list).hasDragHitElement(event)) {
-      return true;
-    }
-
-    // If the position values are negative, it points the out of list.
-    const pos = DragSelector.getScrolledPosition(this.list, event);
-    if (!pos) {
-      return false;
-    }
-    // @ts-ignore: error TS2339: Property 'y' does not exist on type 'Object'.
-    if (pos.x < 0 || pos.y < 0) {
-      return true;
-    }
-
-    // If the item index is out of range, it should start the drag selection.
-    // @ts-ignore: error TS2339: Property 'measureItem' does not exist on type
-    // 'List'.
-    const itemHeight = this.list.measureItem().height;
-    // Faster alternative to Math.floor for non-negative numbers.
-    // @ts-ignore: error TS2339: Property 'y' does not exist on type 'Object'.
-    const itemIndex = ~~(pos.y / itemHeight);
-    const length = this.dataModel?.length ?? 0;
-    if (itemIndex >= length) {
-      return true;
-    }
-
-    // If the pointed item is already selected, it should not start the drag
-    // selection.
-    if (this.lastSelection_ && this.lastSelection_.indexOf(itemIndex) !== -1) {
-      return false;
-    }
-
-    // If the horizontal value is not hit to column, it should start the drag
-    // selection.
-    // @ts-ignore: error TS2339: Property 'x' does not exist on type 'Object'.
-    const hitColumn = this.columnModel.getHitColumn(pos.x);
-    if (!hitColumn) {
-      return true;
-    }
-
-    // Check if the point is on the column contents or not.
-    // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-    switch (this.columnModel.columns_[hitColumn.index].id) {
-      case 'name':
-        const item = this.list.getListItemByIndex(itemIndex);
-        if (!item) {
-          return false;
-        }
-
-        const spanElement = item.querySelector('.filename-label span');
-        const spanRect = spanElement && spanElement.getBoundingClientRect();
-        // The this.list.cachedBounds_ object is set by
-        // DragSelector.getScrolledPosition.
-        // @ts-ignore: error TS2339: Property 'cachedBounds' does not exist on
-        // type 'List'.
-        if (!this.list.cachedBounds) {
-          return true;
-        }
-        const textRight =
-            // @ts-ignore: error TS2339: Property 'cachedBounds' does not exist
-            // on type 'List'.
-            spanRect.left - this.list.cachedBounds.left + spanRect.width;
-        return textRight <= hitColumn.hitPosition;
-      default:
-        return true;
-    }
-  }
-
-  /**
-   * Render the Name column of the detail table.
-   *
-   * Invoked by Table when a file needs to be rendered.
-   *
-   * @param {!Entry} entry The Entry object to render.
-   * @param {string} columnId The id of the column to be rendered.
-   * @param {Table} table The table doing the rendering.
-   * @return {!HTMLDivElement} Created element.
-   * @private
-   */
-  // @ts-ignore: error TS6133: 'table' is declared but its value is never read.
-  renderName_(entry, columnId, table) {
-    const label = /** @type {!HTMLDivElement} */
-        // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-        // type 'FileTable'.
-        (this.ownerDocument.createElement('div'));
-
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    const metadata = this.metadataModel_.getCache(
-        [entry], ['contentMimeType', 'isDlpRestricted'])[0];
-    // @ts-ignore: error TS18048: 'metadata' is possibly 'undefined'.
-    const mimeType = metadata.contentMimeType;
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    const locationInfo = this.volumeManager_.getLocationInfo(entry);
-    const icon = renderFileTypeIcon(
-        // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-        // type 'FileTable'.
-        this.ownerDocument, entry, locationInfo, mimeType);
-    if (FileType.isImage(entry, mimeType) ||
-        FileType.isVideo(entry, mimeType) ||
-        FileType.isAudio(entry, mimeType) || FileType.isRaw(entry, mimeType)) {
-      icon.appendChild(this.renderThumbnail_(entry, icon));
-    }
-    icon.appendChild(this.renderCheckmark_());
-    label.appendChild(icon);
-    // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-    // type 'FileTable'.
-    label.appendChild(renderIconBadge(this.ownerDocument));
-    // @ts-ignore: error TS2339: Property 'entry' does not exist on type
-    // 'HTMLDivElement'.
-    label.entry = entry;
-    label.className = 'detail-name';
-    label.appendChild(
-        // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-        // type 'FileTable'.
-        renderFileNameLabel(this.ownerDocument, entry, locationInfo));
-    if (locationInfo && locationInfo.isDriveBased) {
-      // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-      // type 'FileTable'.
-      const inlineStatus = this.ownerDocument.createElement('xf-inline-status');
-      inlineStatus.classList.add('tast-inline-status');
-      label.appendChild(inlineStatus);
-    }
-    return label;
-  }
-
-  /**
-   * @param {number} index Index of the list item.
-   * @return {string}
-   */
-  getItemLabel(index) {
-    if (index === -1) {
-      return '';
-    }
-
-    /** @type {Entry|FilesAppEntry} */
-    const entry = this.dataModel.item(index);
-    if (!entry) {
-      return '';
-    }
-
-    const locationInfo = this.volumeManager_?.getLocationInfo(entry) || null;
-    return getEntryLabel(locationInfo, entry);
-  }
-
-  /**
-   * Render the Size column of the detail table.
-   *
-   * @param {Entry} entry The Entry object to render.
-   * @param {string} columnId The id of the column to be rendered.
-   * @param {Table} table The table doing the rendering.
-   * @return {!HTMLDivElement} Created element.
-   * @private
-   */
-  // @ts-ignore: error TS6133: 'table' is declared but its value is never read.
-  renderSize_(entry, columnId, table) {
-    const div = /** @type {!HTMLDivElement} */
-        // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-        // type 'FileTable'.
-        (this.ownerDocument.createElement('div'));
-    div.className = 'size';
-    this.updateSize_(div, entry);
-
-    return div;
-  }
-
-  /**
-   * Sets up or updates the size cell.
-   *
-   * @param {HTMLDivElement} div The table cell.
-   * @param {Entry} entry The corresponding entry.
-   * @private
-   */
-  updateSize_(div, entry) {
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    const metadata = this.metadataModel_.getCache(
-        [entry], ['size', 'hosted', 'contentMimeType'])[0];
-    // @ts-ignore: error TS18048: 'metadata' is possibly 'undefined'.
-    const size = metadata.size;
-    // @ts-ignore: error TS18048: 'metadata' is possibly 'undefined'.
-    const special = metadata.hosted ||
-        // @ts-ignore: error TS18048: 'metadata' is possibly 'undefined'.
-        FileType.isEncrypted(entry, metadata.contentMimeType);
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    div.textContent = this.formatter_.formatSize(size, special);
-  }
-
-  /**
-   * Render the Type column of the detail table.
-   *
-   * @param {Entry} entry The Entry object to render.
-   * @param {string} columnId The id of the column to be rendered.
-   * @param {Table} table The table doing the rendering.
-   * @return {!HTMLDivElement} Created element.
-   * @private
-   */
-  // @ts-ignore: error TS6133: 'table' is declared but its value is never read.
-  renderType_(entry, columnId, table) {
-    const div = /** @type {!HTMLDivElement} */
-        // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-        // type 'FileTable'.
-        (this.ownerDocument.createElement('div'));
-    div.className = 'type';
-
-    const mimeType =
-        // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-        this.metadataModel_.getCache([entry], ['contentMimeType'])[0]
-            .contentMimeType;
-    div.textContent =
-        FileListModel.getFileTypeString(FileType.getType(entry, mimeType));
-    return div;
-  }
-
-  /**
-   * Render the Date column of the detail table.
-   *
-   * @param {Entry} entry The Entry object to render.
-   * @param {string} columnId The id of the column to be rendered.
-   * @param {Table} table The table doing the rendering.
-   * @return {HTMLDivElement} Created element.
-   * @private
-   */
-  // @ts-ignore: error TS6133: 'table' is declared but its value is never read.
-  renderDate_(entry, columnId, table) {
-    const div = /** @type {!HTMLDivElement} */
-        // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-        // type 'FileTable'.
-        (this.ownerDocument.createElement('div'));
-
-    div.className = 'dateholder';
-    const label = /** @type {!HTMLDivElement} */
-        // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist
-        // on type 'FileTable'.
-        (this.ownerDocument.createElement('div'));
-    div.appendChild(label);
-    label.className = 'date';
-    this.updateDate_(label, entry);
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    const metadata = this.metadataModel_.getCache(
-        [entry], ['contentMimeType', 'isDlpRestricted'])[0];
-    // @ts-ignore: error TS18048: 'metadata' is possibly 'undefined'.
-    const isEncrypted = FileType.isEncrypted(entry, metadata.contentMimeType);
-    if (isEncrypted) {
-      div.appendChild(this.renderEncryptedIcon_());
-    }
-    if (isDlpEnabled()) {
-      // @ts-ignore: error TS18048: 'metadata' is possibly 'undefined'.
-      div.appendChild(this.renderDlpManagedIcon_(!!metadata.isDlpRestricted));
-    }
-    return div;
-  }
-
-  /**
-   * Sets up or updates the date cell.
-   *
-   * @param {HTMLDivElement} div The table cell.
-   * @param {Entry} entry Entry of file to update.
-   * @private
-   */
-  updateDate_(div, entry) {
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    const item = this.metadataModel_.getCache(
-        [entry], ['modificationTime', 'modificationByMeTime'])[0];
-    const modTime = this.useModificationByMeTime_ ?
-        // @ts-ignore: error TS18048: 'item' is possibly 'undefined'.
-        item.modificationByMeTime || item.modificationTime :
-        // @ts-ignore: error TS18048: 'item' is possibly 'undefined'.
-        item.modificationTime;
-
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    div.textContent = this.formatter_.formatModDate(modTime);
-  }
-
-  updateGroupHeading_() {
-    const fileListModel = /** @type {FileListModel} */ (this.dataModel);
-    if (fileListModel &&
-        fileListModel.groupByField === GROUP_BY_FIELD_MODIFICATION_TIME) {
-      // TODO(crbug.com/1353650): find a way to update heading instead of redraw
-      this.redraw();
-    }
-  }
-
-  /**
-   * Updates the file metadata in the table item.
-   *
-   * @param {Element} item Table item.
-   * @param {Entry} entry File entry.
-   */
-  updateFileMetadata(item, entry) {
-    this.updateDate_(
-        /** @type {!HTMLDivElement} */ (item.querySelector('.date')), entry);
-    this.updateSize_(
-        /** @type {!HTMLDivElement} */ (item.querySelector('.size')), entry);
-  }
-
-  /**
-   * Updates list items 'in place' on metadata change.
-   * @param {string} type Type of metadata change.
-   * @param {Array<Entry>} entries Entries to update.
-   */
-  updateListItemsMetadata(type, entries) {
-    const urls = entriesToURLs(entries);
-    // @ts-ignore: error TS7006: Parameter 'callback' implicitly has an 'any'
-    // type.
-    const forEachCell = (selector, callback) => {
-      // @ts-ignore: error TS2339: Property 'querySelectorAll' does not exist on
-      // type 'FileTable'.
-      const cells = this.querySelectorAll(selector);
-      for (let i = 0; i < cells.length; i++) {
-        const cell = /** @type {HTMLElement} */ (cells[i]);
-        // @ts-ignore: error TS2551: Property 'list_' does not exist on type
-        // 'FileTable'. Did you mean 'list'?
-        const listItem = this.list_.getListItemAncestor(cell);
-        const index = listItem?.listIndex ?? 0;
-        const entry = this.dataModel.item(index);
-        if (entry && urls.indexOf(entry.toURL()) !== -1) {
-          callback.call(this, cell, entry, listItem);
-        }
-      }
-    };
-    if (type === 'filesystem') {
-      // @ts-ignore: error TS7006: Parameter 'unused' implicitly has an 'any'
-      // type.
-      forEachCell('.table-row-cell .date', function(item, entry, unused) {
-        // @ts-ignore: error TS2683: 'this' implicitly has type 'any' because it
-        // does not have a type annotation.
-        this.updateDate_(item, entry);
-      });
-      // @ts-ignore: error TS7006: Parameter 'unused' implicitly has an 'any'
-      // type.
-      forEachCell('.table-row-cell > .size', function(item, entry, unused) {
-        // @ts-ignore: error TS2683: 'this' implicitly has type 'any' because it
-        // does not have a type annotation.
-        this.updateSize_(item, entry);
-      });
-      this.updateGroupHeading_();
-    } else if (type === 'external') {
-      // The cell name does not matter as the entire list item is needed.
-      // @ts-ignore: error TS7006: Parameter 'listItem' implicitly has an 'any'
-      // type.
-      forEachCell('.table-row-cell .date', function(item, entry, listItem) {
-        updateListItemExternalProps(
-            listItem, entry,
-            // @ts-ignore: error TS2683: 'this' implicitly has type 'any'
-            // because it does not have a type annotation.
-            this.metadataModel_.getCache(
-                [entry],
-                [
-                  'availableOffline',
-                  'customIconUrl',
-                  'shared',
-                  'isMachineRoot',
-                  'isExternalMedia',
-                  'hosted',
-                  'pinned',
-                  'syncStatus',
-                  'progress',
-                  'syncCompletedTime',
-                  'shortcut',
-                  'canPin',
-                  'isDlpRestricted',
-                ])[0],
-            isTeamDriveRoot(entry));
-        listItem.toggleAttribute(
-            'disabled',
-            isDlpBlocked(
-                // @ts-ignore: error TS2683: 'this' implicitly has type 'any'
-                // because it does not have a type annotation.
-                entry, assert(this.metadataModel_),
-                // @ts-ignore: error TS2683: 'this' implicitly has type 'any'
-                // because it does not have a type annotation.
-                assert(this.volumeManager_)));
-      });
-    }
-  }
-
-  /**
-   * Renders table row.
-   * @param {function(Entry, Table):void} baseRenderFunction Base renderer.
-   * @param {Entry} entry Corresponding entry.
-   * @return {HTMLLIElement} Created element.
-   * @private
-   */
-  // @ts-ignore: error TS6133: 'renderTableRow_' is declared but its value is
-  // never read.
-  renderTableRow_(baseRenderFunction, entry) {
-    // @ts-ignore: error TS2345: Argument of type 'this' is not assignable to
-    // parameter of type 'Table'.
-    const item = baseRenderFunction(entry, this);
-    // @ts-ignore: error TS2339: Property 'id' does not exist on type 'void'.
-    const nameId = item.id + '-entry-name';
-    // @ts-ignore: error TS2339: Property 'id' does not exist on type 'void'.
-    const sizeId = item.id + '-size';
-    // @ts-ignore: error TS2339: Property 'id' does not exist on type 'void'.
-    const typeId = item.id + '-type';
-    // @ts-ignore: error TS2339: Property 'id' does not exist on type 'void'.
-    const dateId = item.id + '-date';
-    // @ts-ignore: error TS2339: Property 'id' does not exist on type 'void'.
-    const dlpId = item.id + '-dlp-managed-icon';
-    // @ts-ignore: error TS2339: Property 'id' does not exist on type 'void'.
-    const encryptedId = item.id + '-encrypted-icon';
-    decorateListItem(
-        // @ts-ignore: error TS2345: Argument of type 'void' is not assignable
-        // to parameter of type 'ListItem'.
-        item, entry, assert(this.metadataModel_), assert(this.volumeManager_));
-    // @ts-ignore: error TS2339: Property 'setAttribute' does not exist on type
-    // 'void'.
-    item.setAttribute('file-name', entry.name);
-    // @ts-ignore: error TS2339: Property 'querySelector' does not exist on type
-    // 'void'.
-    item.querySelector('.detail-name').setAttribute('id', nameId);
-    // @ts-ignore: error TS2339: Property 'querySelector' does not exist on type
-    // 'void'.
-    item.querySelector('.size').setAttribute('id', sizeId);
-    // @ts-ignore: error TS2339: Property 'querySelector' does not exist on type
-    // 'void'.
-    item.querySelector('.type').setAttribute('id', typeId);
-    // @ts-ignore: error TS2339: Property 'querySelector' does not exist on type
-    // 'void'.
-    item.querySelector('.date').setAttribute('id', dateId);
-    // @ts-ignore: error TS2339: Property 'querySelector' does not exist on type
-    // 'void'.
-    const dlpManagedIcon = item.querySelector('.dlp-managed-icon');
-    if (dlpManagedIcon) {
-      dlpManagedIcon.setAttribute('id', dlpId);
-      // @ts-ignore: error TS2304: Cannot find name 'FilesTooltip'.
-      /** @type {!FilesTooltip} */ (
-          // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist
-          // on type 'FileTable'.
-          this.ownerDocument.querySelector('files-tooltip'))
-          // @ts-ignore: error TS2339: Property 'querySelectorAll' does not
-          // exist on type 'void'.
-          .addTargets(item.querySelectorAll('.dlp-managed-icon'));
-    }
-    // @ts-ignore: error TS2339: Property 'querySelector' does not exist on type
-    // 'void'.
-    const encryptedIcon = item.querySelector('.encrypted-icon');
-    if (encryptedIcon) {
-      encryptedIcon.setAttribute('id', encryptedId);
-    }
-
-    // @ts-ignore: error TS2339: Property 'setAttribute' does not exist on type
-    // 'void'.
-    item.setAttribute(
-        'aria-labelledby',
-        `${nameId} column-size ${sizeId} column-type ${
-            typeId} column-modificationTime ${dateId} ${encryptedId}`);
-    // @ts-ignore: error TS2322: Type 'void' is not assignable to type
-    // 'HTMLLIElement'.
-    return item;
-  }
-
-  /**
-   * Renders the file thumbnail in the detail table.
-   * @param {Entry} entry The Entry object to render.
-   * @param {HTMLDivElement} parent The parent DOM element.
-   * @return {!HTMLDivElement} Created element.
-   * @private
-   */
-  renderThumbnail_(entry, parent) {
-    const box = /** @type {!HTMLDivElement} */
-        // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-        // type 'FileTable'.
-        (this.ownerDocument.createElement('div'));
-    box.className = 'detail-thumbnail';
-
-    // Set thumbnail if it's already in cache.
-    const thumbnailData = this.listThumbnailLoader_ ?
-        this.listThumbnailLoader_.getThumbnailFromCache(entry) :
-        null;
-    if (thumbnailData && thumbnailData.dataUrl) {
-      this.setThumbnailImage_(box, thumbnailData.dataUrl);
-      parent.classList.add('has-thumbnail');
-    }
-
-    return box;
-  }
-
-  /**
-   * Sets thumbnail image to the box.
-   * @param {!HTMLDivElement} box Detail thumbnail div element.
-   * @param {string} dataUrl Data url of thumbnail.
-   * @private
-   */
-  setThumbnailImage_(box, dataUrl) {
-    const thumbnail = box.ownerDocument.createElement('div');
-    thumbnail.classList.add('thumbnail');
-    thumbnail.style.backgroundImage = 'url(' + dataUrl + ')';
-    const oldThumbnails = box.querySelectorAll('.thumbnail');
-
-    for (let i = 0; i < oldThumbnails.length; i++) {
-      // @ts-ignore: error TS2345: Argument of type 'Element | undefined' is not
-      // assignable to parameter of type 'Node'.
-      box.removeChild(oldThumbnails[i]);
-    }
-
-    box.appendChild(thumbnail);
-  }
-
-  /**
-   * Clears thumbnail image from the box.
-   * @param {!HTMLDivElement} box Detail thumbnail div element.
-   * @private
-   */
-  clearThumbnailImage_(box) {
-    const oldThumbnails = box.querySelectorAll('.thumbnail');
-
-    for (let i = 0; i < oldThumbnails.length; i++) {
-      // @ts-ignore: error TS2345: Argument of type 'Element | undefined' is not
-      // assignable to parameter of type 'Node'.
-      box.removeChild(oldThumbnails[i]);
-    }
-  }
-
-  /**
-   * Renders the selection checkmark in the detail table.
-   * @return {!HTMLDivElement} Created element.
-   * @private
-   */
-  renderCheckmark_() {
-    const checkmark = /** @type {!HTMLDivElement} */
-        // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-        // type 'FileTable'.
-        (this.ownerDocument.createElement('div'));
-    checkmark.className = 'detail-checkmark';
-    return checkmark;
-  }
-
-  /**
-   * Renders the DLP managed icon in the detail table.
-   * @param {!boolean} isDlpRestricted Whether the icon should be shown.
-   * @return {!HTMLDivElement} Created element.
-   * @private
-   */
-  renderDlpManagedIcon_(isDlpRestricted) {
-    const icon = /** @type {!HTMLDivElement} */
-        // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-        // type 'FileTable'.
-        (this.ownerDocument.createElement('div'));
-    icon.className = 'dlp-managed-icon';
-    icon.toggleAttribute('has-tooltip');
-    icon.dataset['tooltipLinkHref'] = str('DLP_HELP_URL');
-    icon.dataset['tooltipLinkAriaLabel'] = str('DLP_MANAGED_ICON_TOOLTIP_DESC');
-    icon.dataset['tooltipLinkText'] = str('DLP_MANAGED_ICON_TOOLTIP_LINK');
-    icon.setAttribute('aria-label', str('DLP_MANAGED_ICON_TOOLTIP'));
-    icon.toggleAttribute('show-card-tooltip');
-    icon.classList.toggle('is-dlp-restricted', isDlpRestricted);
-    icon.toggleAttribute('aria-hidden', isDlpRestricted);
-    return icon;
-  }
-
-  /**
-   * Renders the encrypted icon in the detail table, used to mark Google Drive
-   * CSE files.
-   * @return {!HTMLDivElement} Created element.
-   * @private
-   */
-  renderEncryptedIcon_() {
-    const icon = /** @type {!HTMLDivElement} */
-        // @ts-ignore: error TS2339: Property 'ownerDocument' does not exist on
-        // type 'FileTable'.
-        (this.ownerDocument.createElement('div'));
-    icon.className = 'encrypted-icon';
-    icon.setAttribute('aria-label', str('ENCRYPTED_ICON_TOOLTIP'));
-    // @ts-ignore: error TS2304: Cannot find name 'FilesTooltip'.
-    /** @type {!FilesTooltip} */ (document.querySelector('files-tooltip'))
-        .addTarget(icon);
-    return icon;
-  }
-
-  /**
-   * Redraws the UI. Skips multiple consecutive calls.
-   */
-  relayout() {
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    this.relayoutRateLimiter_.run();
-  }
-
-  /**
-   * Redraws the UI immediately.
-   * @private
-   */
-  // @ts-ignore: error TS6133: 'relayoutImmediately_' is declared but its value
-  // is never read.
-  relayoutImmediately_() {
-    // @ts-ignore: error TS2339: Property 'clientWidth' does not exist on type
-    // 'FileTable'.
-    if (this.clientWidth > 0) {
-      this.normalizeColumns();
-    }
-    this.redraw();
-    dispatchSimpleEvent(this.list, 'relayout');
-  }
-}
-
-/**
- * Inherits from Table.
- */
-FileTable.prototype.__proto__ = Table.prototype;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table.ts b/ui/file_manager/file_manager/foreground/js/ui/file_table.ts
new file mode 100644
index 0000000..6e998113
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_table.ts
@@ -0,0 +1,1146 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {dispatchSimpleEvent} from 'chrome://resources/ash/common/cr_deprecated.js';
+
+import {RateLimiter} from '../../../common/js/async_util.js';
+import {maybeShowTooltip} from '../../../common/js/dom_utils.js';
+import {entriesToURLs, isTeamDriveRoot} from '../../../common/js/entry_utils.js';
+import {FileType} from '../../../common/js/file_type.js';
+import {isDlpEnabled} from '../../../common/js/flags.js';
+import {getEntryLabel, str, strf} from '../../../common/js/translations.js';
+import type {FilesAppEntry} from '../../../externs/files_app_entry_interfaces.js';
+import type {VolumeManager} from '../../../externs/volume_manager.js';
+import {FileListModel, GROUP_BY_FIELD_MODIFICATION_TIME} from '../file_list_model.js';
+import {ListThumbnailLoader, type ThumbnailLoadedEvent} from '../list_thumbnail_loader.js';
+import {MetadataModel} from '../metadata/metadata_model.js';
+
+import type {A11yAnnounce} from './a11y_announce.js';
+import {DragSelector} from './drag_selector.js';
+import {FileMetadataFormatter} from './file_metadata_formatter.js';
+import {decorateListItem, FileTableList, isDlpBlocked, renderFileNameLabel, renderFileTypeIcon, renderIconBadge, updateCacheItemInlineStatus, updateListItemExternalProps} from './file_table_list.js';
+import type {ListItem} from './list_item.js';
+import {Table} from './table/table.js';
+import {TableColumn} from './table/table_column.js';
+import {TableColumnModel} from './table/table_column_model.js';
+
+
+type ColumnWidthConfig = Record<string, {width: number}>;
+
+interface ColumnHitResult {
+  index: number;
+  width: number;
+  hitPosition: number;
+}
+
+/**
+ * Custom column model for advanced auto-resizing.
+ */
+export class FileTableColumnModel extends TableColumnModel {
+  private snapshot_: ColumnSnapshot|null = null;
+
+  /**
+   * Sets column width so that the column dividers move to the specified
+   * position. This function also check the width of each column and keep the
+   * width larger than MIN_WIDTH.
+   *
+   * @param newPos Positions of each column dividers.
+   */
+  private applyColumnPositions_(newPos: number[]) {
+    // Check the minimum width and adjust the positions.
+    for (let i = 0; i < newPos.length - 2; i++) {
+      if (!this.columns_[i]!.visible) {
+        newPos[i + 1] = newPos[i]!;
+      } else if (newPos[i + 1]! - newPos[i]! < MIN_WIDTH) {
+        newPos[i + 1] = newPos[i]! + MIN_WIDTH;
+      }
+    }
+    for (let i = newPos.length - 1; i >= 2; i--) {
+      if (!this.columns_[i - 1]!.visible) {
+        newPos[i - 1] = newPos[i]!;
+      } else if (newPos[i]! - newPos[i - 1]! < MIN_WIDTH) {
+        newPos[i - 1] = newPos[i]! - MIN_WIDTH;
+      }
+    }
+    // Set the new width of columns
+    for (let i = 0; i < this.columns_.length; i++) {
+      if (!this.columns_[i]!.visible) {
+        this.columns_[i]!.width = 0;
+      } else {
+        // Make sure each cell has the minimum width. This is necessary when the
+        // window size is too small to contain all the columns.
+        this.columns_[i]!.width =
+            Math.max(MIN_WIDTH, newPos[i + 1]! - newPos[i]!);
+      }
+    }
+  }
+
+  /**
+   * Normalizes widths to make their sum 100% if possible. Uses the proportional
+   * approach with some additional constraints.
+   *
+   * @param contentWidth Target width.
+   */
+  override normalizeWidths(contentWidth: number) {
+    let totalWidth = 0;
+    // Some columns have fixed width.
+    for (let i = 0; i < this.columns_.length; i++) {
+      totalWidth += this.columns_[i]!.width;
+    }
+    const positions = [0];
+    let sum = 0;
+    for (let i = 0; i < this.columns_.length; i++) {
+      const column = this.columns_[i]!;
+      sum += column.width;
+      // Faster alternative to Math.floor for non-negative numbers.
+      positions[i + 1] = ~~(contentWidth * sum / totalWidth);
+    }
+    this.applyColumnPositions_(positions);
+  }
+
+  /**
+   * Handles to the start of column resizing by splitters.
+   */
+  handleSplitterDragStart() {
+    this.initializeColumnPos();
+  }
+
+  /**
+   * Handles to the end of column resizing by splitters.
+   */
+  handleSplitterDragEnd() {
+    this.destroyColumnPos();
+  }
+
+  /**
+   * Initialize a column snapshot which is used in setWidthAndKeepTotal().
+   */
+  initializeColumnPos() {
+    this.snapshot_ = new ColumnSnapshot(this.columns_);
+  }
+
+  /**
+   * Destroy the column snapshot which is used in setWidthAndKeepTotal().
+   */
+  destroyColumnPos() {
+    this.snapshot_ = null;
+  }
+
+  /**
+   * Sets the width of column while keeping the total width of table.
+   * Before and after calling this method, you must initialize and destroy
+   * columnPos with initializeColumnPos() and destroyColumnPos().
+   * @param columnIndex Index of column that is resized.
+   * @param columnWidth New width of the column.
+   */
+  setWidthAndKeepTotal(columnIndex: number, columnWidth: number) {
+    columnWidth = Math.max(columnWidth, MIN_WIDTH);
+    this.snapshot_!.setWidth(columnIndex, columnWidth);
+    this.applyColumnPositions_(this.snapshot_!.newPos);
+
+    // Notify about resizing
+    dispatchSimpleEvent(this, 'resize');
+  }
+
+  /**
+   * Obtains a column by the specified horizontal position.
+   * @param x Horizontal position.
+   * @return The object that contains column index, column width, and
+   *     hitPosition where the horizontal position is hit in the column.
+   */
+  getHitColumn(x: number): null|ColumnHitResult {
+    let i = 0;
+    for (; i < this.columns_.length && x >= this.columns_[i]!.width; i++) {
+      x -= this.columns_[i]!.width;
+    }
+    if (i >= this.columns_.length) {
+      return null;
+    }
+    return {index: i, hitPosition: x, width: this.columns_[i]!.width};
+  }
+
+  override setVisible(index: number, visible: boolean) {
+    if (index < 0 || index > this.columns_.length - 1) {
+      return;
+    }
+
+    const column = this.columns_[index]!;
+    if (column.visible === visible) {
+      return;
+    }
+
+    // Re-layout the table.  This overrides the default column layout code in
+    // the parent class.
+    const snapshot = new ColumnSnapshot(this.columns_);
+
+    column.visible = visible;
+
+    // Keep the current column width, but adjust the other columns to
+    // accommodate the new column.
+    snapshot.setWidth(index, column.width);
+    this.applyColumnPositions_(snapshot.newPos);
+  }
+
+  /**
+   * Export a set of column widths for use by #restoreColumnWidths.  Use these
+   * two methods instead of manually saving and setting column widths, because
+   * doing the latter will not correctly save/restore column widths for hidden
+   * columns.
+   * see #restoreColumnWidths
+   * @return config
+   */
+  exportColumnConfig(): ColumnWidthConfig {
+    // Make a snapshot, and use that to compute a column layout where all the
+    // columns are visible.
+    const snapshot = new ColumnSnapshot(this.columns_);
+    for (let i = 0; i < this.columns_.length; i++) {
+      if (!this.columns_[i]!.visible) {
+        snapshot.setWidth(i, this.columns_[i]!.absoluteWidth);
+      }
+    }
+    // Export the column widths.
+    const config: ColumnWidthConfig = {};
+    for (let i = 0; i < this.columns_.length; i++) {
+      config[this.columns_[i]!.id] = {
+        width: snapshot.newPos[i + 1]! - snapshot.newPos[i]!,
+      };
+    }
+    return config;
+  }
+
+  /**
+   * Restores a set of column widths previously created by calling
+   * #exportColumnConfig.
+   * see #exportColumnConfig
+   */
+  restoreColumnConfig(config: ColumnWidthConfig) {
+    // Columns must all be made visible before restoring their widths.  Save the
+    // current visibility so it can be restored after.
+    const visibility = [];
+    for (let i = 0; i < this.columns_.length; i++) {
+      visibility[i] = this.columns_[i]!.visible;
+      this.columns_[i]!.visible = true;
+    }
+
+    // Do not use external setters (e.g. #setVisible, #setWidth) here because
+    // they trigger layout thrash, and also try to dynamically resize columns,
+    // which interferes with restoring the old column layout.
+    for (const columnId in config) {
+      const column = this.columns_[this.indexOf(columnId)];
+      if (column) {
+        // Set column width.  Ignore invalid widths.
+        const width = ~~config[columnId]!.width;
+        if (width > 0) {
+          column.width = width;
+        }
+      }
+    }
+
+    // Restore column visibility.  Use setVisible here, to trigger table
+    // relayout.
+    for (let i = 0; i < this.columns_.length; i++) {
+      this.setVisible(i, visibility[i]!);
+    }
+  }
+}
+
+/**
+ * TODO: Move this to be a method of TableColumn.
+ *
+ * Customize the column header to decorate with a11y attributes that announces
+ * the sorting used when clicked.
+ *
+ * @this {TableColumn} Bound by TableHeader before calling.
+ * @param table Table being rendered.
+ */
+function renderHeader(this: TableColumn, table: FileTable): Element {
+  const column = this;
+  const container = table.ownerDocument.createElement('div');
+  container.classList.add('table-label-container');
+
+  const textElement = table.ownerDocument.createElement('span');
+  textElement.setAttribute('id', `column-${column.id}`);
+  textElement.textContent = column.name;
+  const dm = table.dataModel;
+
+  let sortOrder = column.defaultOrder;
+  let isSorted = false;
+  if (dm && dm.sortStatus.field === column.id) {
+    isSorted = true;
+    // Here we have to flip, because clicking will perform the opposite sorting.
+    sortOrder = dm.sortStatus.direction === 'desc' ? 'asc' : 'desc';
+  }
+
+  textElement.setAttribute('aria-describedby', 'sort-column-' + sortOrder);
+  textElement.setAttribute('role', 'button');
+  container.appendChild(textElement);
+
+  const icon = document.createElement('cr-icon-button');
+  const iconName = sortOrder === 'desc' ? 'up' : 'down';
+  icon.setAttribute('iron-icon', `files16:arrow_${iconName}_small`);
+  // If we're the sorting column make the icon a tab target.
+  if (isSorted) {
+    icon.id = 'sort-direction-button';
+    icon.setAttribute('tabindex', '0');
+    icon.setAttribute('aria-hidden', 'false');
+    if (sortOrder === 'asc') {
+      icon.setAttribute('aria-label', str('COLUMN_ASC_SORT_MESSAGE'));
+    } else {
+      icon.setAttribute('aria-label', str('COLUMN_DESC_SORT_MESSAGE'));
+    }
+  } else {
+    icon.setAttribute('tabindex', '-1');
+    icon.setAttribute('aria-hidden', 'true');
+  }
+  icon.classList.add('sort-icon', 'no-overlap');
+
+  container.classList.toggle('not-sorted', !isSorted);
+  container.classList.toggle('sorted', isSorted);
+
+  container.appendChild(icon);
+
+  return container;
+}
+
+/**
+ * Minimum width of column. Note that is not marked private as it is used in the
+ * unit tests.
+ */
+export const MIN_WIDTH = 40;
+
+/**
+ * A helper class for performing resizing of columns.
+ */
+class ColumnSnapshot {
+  private columnPos_: number[];
+  newPos: number[];
+
+  /**
+   */
+  constructor(columns: TableColumn[]) {
+    this.columnPos_ = [0];
+    for (let i = 0; i < columns.length; i++) {
+      this.columnPos_[i + 1] = columns[i]!.width + this.columnPos_[i]!;
+    }
+
+    /**
+     * Starts off as a copy of the current column positions, but gets modified.
+     */
+    this.newPos = this.columnPos_.slice(0);
+  }
+
+  /**
+   * Set the width of the given column.  The snapshot will keep the total width
+   * of the table constant.
+   */
+  setWidth(index: number, width: number) {
+    // Skip to resize 'selection' column
+    if (index < 0 || index >= this.columnPos_.length - 1 || !this.columnPos_) {
+      return;
+    }
+
+    // Round up if the column is shrinking, and down if the column is expanding.
+    // This prevents off-by-one drift.
+    const currentWidth = this.columnPos_[index + 1]! - this.columnPos_[index]!;
+    const round = width < currentWidth ? Math.ceil : Math.floor;
+
+    // Calculate new positions of column splitters.
+    const newPosStart = this.columnPos_[index]! + width;
+    const posEnd = this.columnPos_[this.columnPos_.length - 1]!;
+    for (let i = 0; i < index + 1; i++) {
+      this.newPos[i] = this.columnPos_[i]!;
+    }
+    for (let i = index + 1; i < this.columnPos_.length - 1; i++) {
+      const posStart = this.columnPos_[index + 1]!;
+      this.newPos[i] = (posEnd - newPosStart) *
+              (this.columnPos_[i]! - posStart) / (posEnd - posStart) +
+          newPosStart;
+      this.newPos[i] = round(this.newPos[i]!);
+    }
+    this.newPos[index] = this.columnPos_[index]!;
+    this.newPos[this.columnPos_.length - 1] = posEnd;
+  }
+}
+
+/**
+ * File list Table View.
+ */
+export class FileTable extends Table {
+  private beginIndex_: number = 0;
+  private endIndex_: number = 0;
+  private listThumbnailLoader_: ListThumbnailLoader|null = null;
+  private relayoutRateLimiter_: RateLimiter|null = null;
+  private metadataModel_: MetadataModel|null = null;
+  private formatter_: FileMetadataFormatter|null = null;
+  private useModificationByMeTime_: boolean = false;
+  private volumeManager_: VolumeManager|null = null;
+  private lastSelection_: unknown[] = [];
+  private onThumbnailLoadedBound_: null|((e: Event) => void) = null;
+  a11y: A11yAnnounce|null = null;
+
+  constructor() {
+    super();
+
+    throw new Error('Designed to decorate elements');
+  }
+
+  /**
+   * Decorates the element.
+   * @param self Table to decorate.
+   * @param metadataModel To retrieve metadata.
+   * @param volumeManager To retrieve volume info.
+   * @param a11y FileManagerUI to be able to announce a11y
+   *     messages.
+   * @param fullPage True if it's full page File Manager, False if a
+   *    file open/save dialog.
+   */
+  static override decorate(
+      el: Element, metadataModel: MetadataModel, volumeManager: VolumeManager,
+      a11y: A11yAnnounce, fullPage: boolean) {
+    Table.decorate(el);
+    Object.setPrototypeOf(el, FileTable.prototype);
+    const self = el as FileTable;
+    FileTableList.decorate(self.list);
+    const list = self.list as FileTableList;
+    list.setOnMergeItems(self.updateHighPriorityRange_.bind(self));
+    self.metadataModel_ = metadataModel;
+    self.volumeManager_ = volumeManager;
+    self.a11y = a11y;
+
+    // Force the list's ending spacer to be tall enough to allow overscroll.
+    const endSpacer = self.querySelector('.spacer:last-child');
+    if (endSpacer) {
+      endSpacer.classList.add('signals-overscroll');
+    }
+
+    self.listThumbnailLoader_ = null;
+    self.beginIndex_ = 0;
+    self.endIndex_ = 0;
+    self.onThumbnailLoadedBound_ = self.onThumbnailLoaded_.bind(self);
+
+    self.useModificationByMeTime_ = false;
+
+    const nameColumn =
+        new TableColumn('name', str('NAME_COLUMN_LABEL'), fullPage ? 386 : 324);
+    nameColumn.renderFunction = self.renderName_.bind(self);
+    nameColumn.headerRenderFunction = renderHeader;
+
+    const sizeColumn =
+        new TableColumn('size', str('SIZE_COLUMN_LABEL'), 110, false);
+    sizeColumn.renderFunction = self.renderSize_.bind(self);
+    sizeColumn.defaultOrder = 'desc';
+    sizeColumn.headerRenderFunction = renderHeader;
+
+    const typeColumn =
+        new TableColumn('type', str('TYPE_COLUMN_LABEL'), fullPage ? 110 : 110);
+    typeColumn.renderFunction = self.renderType_.bind(self);
+    typeColumn.headerRenderFunction = renderHeader;
+
+    const modTimeColumn = new TableColumn(
+        'modificationTime', str('DATE_COLUMN_LABEL'), fullPage ? 150 : 210);
+    modTimeColumn.renderFunction = self.renderDate_.bind(self);
+    modTimeColumn.defaultOrder = 'desc';
+    modTimeColumn.headerRenderFunction = renderHeader;
+
+    const columns = [nameColumn, sizeColumn, typeColumn, modTimeColumn];
+
+    const columnModel = new FileTableColumnModel(columns);
+
+    self.columnModel = columnModel;
+
+    self.formatter_ = new FileMetadataFormatter();
+
+    self.setRenderFunction(
+        self.renderTableRow_.bind(self, self.getRenderFunction()));
+
+    // Keep focus on the file list when clicking on the header.
+    self.header.addEventListener('mousedown', e => {
+      self.list.focus();
+      e.preventDefault();
+    });
+
+    self.relayoutRateLimiter_ =
+        new RateLimiter(self.relayoutImmediately_.bind(self));
+
+    // Save the last selection. This is used by shouldStartDragSelection.
+    self.list.addEventListener('mousedown', (_e: Event) => {
+      self.lastSelection_ = self.selectionModel.selectedIndexes;
+    }, true);
+    self.list.addEventListener('touchstart', (_e: Event) => {
+      self.lastSelection_ = self.selectionModel.selectedIndexes;
+    }, true);
+    list.shouldStartDragSelection = self.shouldStartDragSelection_.bind(self);
+
+    list.addEventListener(
+        'mouseover', self.onMouseOver_.bind(self), {passive: true});
+
+    // Update the item's inline status when it's restored from List's cache.
+    list.addEventListener(
+        'cachedItemRestored',
+        (e) => updateCacheItemInlineStatus(
+            e.detail, self.dataModel, self.metadataModel_!));
+  }
+
+  private onMouseOver_(event: MouseEvent) {
+    this.maybeShowToolTip(event);
+  }
+
+  maybeShowToolTip(event: MouseEvent) {
+    const target = event.composedPath()[0] as HTMLElement;
+    if (!target) {
+      return;
+    }
+    if (!target.classList.contains('detail-name')) {
+      return;
+    }
+    const labelElement = target.querySelector<HTMLElement>('.filename-label');
+    if (!labelElement) {
+      return;
+    }
+
+    maybeShowTooltip(labelElement, labelElement.innerText);
+  }
+
+  /**
+   * Sort data by the given column. Overridden to add the a11y message after
+   * sorting.
+   * @param index The index of the column to sort by.
+   */
+  override sort(index: number) {
+    const cm = this.columnModel;
+    if (!this.dataModel) {
+      return;
+    }
+    const fieldName = cm.getId(index);
+    const sortStatus = this.dataModel.sortStatus;
+
+    let sortDirection = cm.getDefaultOrder(index);
+    if (sortStatus.field === fieldName) {
+      // If it's sorting the column that's already sorted, we need to flip the
+      // sorting order.
+      sortDirection = sortStatus.direction === 'desc' ? 'asc' : 'desc';
+    }
+
+    const msgId =
+        sortDirection === 'asc' ? 'COLUMN_SORTED_ASC' : 'COLUMN_SORTED_DESC';
+    const msg = strf(msgId, fieldName);
+
+    // Delegate to parent to sort.
+    super.sort(index);
+    this.a11y!.speakA11yMessage(msg);
+  }
+
+  /**
+   */
+  override onDataModelSorted() {
+    const fileListModel = this.dataModel as FileListModel;
+    const hasGroupHeadingAfterSort = fileListModel.shouldShowGroupHeading();
+    // Sort doesn't trigger redraw sometimes, e.g. if we sort by Name for now,
+    // then we sort by time, if the list order doesn't change, no permuted event
+    // is triggered, thus no redraw is triggered. In this scenario, we need to
+    // manually trigger a redraw to remove/add the group heading.
+    if (hasGroupHeadingAfterSort !== fileListModel.hasGroupHeadingBeforeSort) {
+      this.list.redraw();
+    }
+  }
+
+  /**
+   * Updates high priority range of list thumbnail loader based on current
+   * viewport.
+   *
+   * @param beginIndex Begin index.
+   * @param endIndex End index.
+   */
+  private updateHighPriorityRange_(beginIndex: number, endIndex: number) {
+    // Keep these values to set range when a new list thumbnail loader is set.
+    this.beginIndex_ = beginIndex;
+    this.endIndex_ = endIndex;
+
+    if (this.listThumbnailLoader_ !== null) {
+      this.listThumbnailLoader_.setHighPriorityRange(beginIndex, endIndex);
+    }
+  }
+
+  /**
+   * Sets list thumbnail loader.
+   * @param listThumbnailLoader A list thumbnail loader.
+   */
+  setListThumbnailLoader(listThumbnailLoader: ListThumbnailLoader) {
+    if (this.listThumbnailLoader_) {
+      this.listThumbnailLoader_.removeEventListener(
+          'thumbnailLoaded', this.onThumbnailLoadedBound_);
+    }
+
+    this.listThumbnailLoader_ = listThumbnailLoader;
+
+    if (this.listThumbnailLoader_) {
+      this.listThumbnailLoader_.addEventListener(
+          'thumbnailLoaded', this.onThumbnailLoadedBound_);
+      this.listThumbnailLoader_.setHighPriorityRange(
+          this.beginIndex_, this.endIndex_);
+    }
+  }
+
+  /**
+   * Returns the element containing the thumbnail of a certain list item as
+   * background image.
+   * @param index The index of the item containing the desired
+   *     thumbnail.
+   * @return The element containing the thumbnail, or null, if an
+   *     error occurred.
+   */
+  getThumbnail(index: number): null|Element {
+    const listItem = this.getListItemByIndex(index);
+    if (!listItem) {
+      return null;
+    }
+    const container = listItem.querySelector('.detail-thumbnail');
+    if (!container) {
+      return null;
+    }
+    return container.querySelector('.thumbnail');
+  }
+
+  /**
+   * Handles thumbnail loaded event.
+   * @param e An event.
+   */
+  private onThumbnailLoaded_(e: Event) {
+    const event = e as ThumbnailLoadedEvent;
+    const listItem = this.getListItemByIndex(event.index);
+    if (listItem) {
+      const box = listItem.querySelector<HTMLDivElement>('.detail-thumbnail');
+      if (box) {
+        if (event.dataUrl) {
+          this.setThumbnailImage_(box, event.dataUrl);
+        } else {
+          this.clearThumbnailImage_(box);
+        }
+        const icon = listItem.querySelector<HTMLElement>('.detail-icon')!;
+        icon.classList.toggle('has-thumbnail', !!event.dataUrl);
+      }
+    }
+  }
+
+  /**
+   * Adjust column width to fit its content.
+   * @param index Index of the column to adjust width.
+   */
+  override fitColumn(index: number) {
+    const render = this.columnModel.getRenderFunction(index);
+    const MAXIMUM_ROWS_TO_MEASURE = 1000;
+
+    // Create a temporaty list item, put all cells into it and measure its
+    // width. Then remove the item. It fits "list > *" CSS rules.
+    const container = this.ownerDocument.createElement('li');
+    container.style.display = 'inline-block';
+    container.style.textAlign = 'start';
+    // The container will have width of the longest cell.
+    container.style.webkitBoxOrient = 'vertical';
+
+    // Select at most MAXIMUM_ROWS_TO_MEASURE items around visible area.
+    const items = this.list.getItemsInViewPort(
+        this.list.scrollTop, this.list.clientHeight);
+    const firstIndex = Math.floor(
+        Math.max(0, (items.last + items.first - MAXIMUM_ROWS_TO_MEASURE) / 2));
+    const lastIndex =
+        Math.min(this.dataModel.length, firstIndex + MAXIMUM_ROWS_TO_MEASURE);
+    for (let i = firstIndex; i < lastIndex; i++) {
+      const item = this.dataModel.item(i);
+      const div = this.ownerDocument.createElement('div');
+      div.className = 'table-row-cell';
+      div.appendChild(render(item, this.columnModel.getId(index)!, this));
+      container.appendChild(div);
+    }
+    this.list.appendChild(container);
+    const width = parseFloat(window.getComputedStyle(container).width);
+    this.list.removeChild(container);
+
+    const cm = this.columnModel as FileTableColumnModel;
+    cm.initializeColumnPos();
+    cm.setWidthAndKeepTotal(index, Math.ceil(width));
+    cm.destroyColumnPos();
+  }
+
+  /**
+   * Sets date and time format.
+   * @param use12hourClock True if 12 hours clock, False if 24 hours.
+   */
+  setDateTimeFormat(use12hourClock: boolean) {
+    this.formatter_!.setDateTimeFormat(use12hourClock);
+  }
+
+  /**
+   * Sets whether to use modificationByMeTime as "Last Modified" time.
+   */
+  setUseModificationByMeTime(useModificationByMeTime: boolean) {
+    this.useModificationByMeTime_ = useModificationByMeTime;
+  }
+
+  /**
+   * Obtains if the drag selection should be start or not by referring the mouse
+   * event.
+   * @param event Drag start event.
+   * @return True if the mouse is hit to the background of the list,
+   * or certain areas of the inside of the list that would start a drag
+   * selection.
+   */
+  private shouldStartDragSelection_(event: MouseEvent): boolean {
+    // If the shift key is pressed, it should starts drag selection.
+    if (event.shiftKey) {
+      return true;
+    }
+
+    const list = this.list as FileTableList;
+    // If we're outside of the element list, start the drag selection.
+    if (!list.hasDragHitElement(event)) {
+      return true;
+    }
+
+    // If the position values are negative, it points the out of list.
+    const pos = DragSelector.getScrolledPosition(this.list, event);
+    if (!pos) {
+      return false;
+    }
+    if (pos.x < 0 || pos.y < 0) {
+      return true;
+    }
+
+    // If the item index is out of range, it should start the drag selection.
+    const itemHeight = this.list.measureItem().height;
+    // Faster alternative to Math.floor for non-negative numbers.
+    const itemIndex = ~~(pos.y / itemHeight);
+    const length = this.dataModel?.length ?? 0;
+    if (itemIndex >= length) {
+      return true;
+    }
+
+    // If the pointed item is already selected, it should not start the drag
+    // selection.
+    if (this.lastSelection_ && this.lastSelection_.indexOf(itemIndex) !== -1) {
+      return false;
+    }
+
+    const cm = this.columnModel as FileTableColumnModel;
+    // If the horizontal value is not hit to column, it should start the drag
+    // selection.
+    const hitColumn = cm.getHitColumn(pos.x);
+    if (!hitColumn) {
+      return true;
+    }
+
+    // Check if the point is on the column contents or not.
+    switch (cm.getId(hitColumn.index)) {
+      case 'name':
+        const item = this.list.getListItemByIndex(itemIndex);
+        if (!item) {
+          return false;
+        }
+
+        const spanElement = item.querySelector('.filename-label span')!;
+        const spanRect = spanElement && spanElement.getBoundingClientRect();
+        // The `list.cachedBounds` is set by DragSelector.getScrolledPosition.
+        if (!this.list.cachedBounds) {
+          return true;
+        }
+        const textRight =
+            spanRect.left - this.list.cachedBounds.left + spanRect.width;
+        return textRight <= hitColumn.hitPosition;
+      default:
+        return true;
+    }
+  }
+
+  /**
+   * Render the Name column of the detail table.
+   *
+   * Invoked by Table when a file needs to be rendered.
+   *
+   * @param entry The Entry object to render.
+   * @param _columnId The id of the column to be rendered.
+   * @param _table The table doing the rendering.
+   * @return Created element.
+   */
+  private renderName_(entry: Entry, _columnId: string, _table: Table):
+      HTMLDivElement {
+    const label = this.ownerDocument.createElement('div');
+
+    const metadata = this.metadataModel_!.getCache(
+        [entry], ['contentMimeType', 'isDlpRestricted'])[0]!;
+    const mimeType = metadata.contentMimeType;
+    const locationInfo = this.volumeManager_!.getLocationInfo(entry);
+    const icon =
+        renderFileTypeIcon(this.ownerDocument, entry, locationInfo, mimeType);
+    if (FileType.isImage(entry, mimeType) ||
+        FileType.isVideo(entry, mimeType) ||
+        FileType.isAudio(entry, mimeType) || FileType.isRaw(entry, mimeType)) {
+      icon.appendChild(this.renderThumbnail_(entry, icon));
+    }
+    icon.appendChild(this.renderCheckmark_());
+    label.appendChild(icon);
+    label.appendChild(renderIconBadge(this.ownerDocument));
+    (label as HTMLDivElement & {entry: Entry}).entry = entry;
+    label.className = 'detail-name';
+    label.appendChild(
+        renderFileNameLabel(this.ownerDocument, entry, locationInfo));
+    if (locationInfo && locationInfo.isDriveBased) {
+      const inlineStatus = this.ownerDocument.createElement('xf-inline-status');
+      inlineStatus.classList.add('tast-inline-status');
+      label.appendChild(inlineStatus);
+    }
+    return label;
+  }
+
+  /**
+   * @param index Index of the list item.
+   */
+  getItemLabel(index: number): string {
+    if (index === -1) {
+      return '';
+    }
+
+    const entry = this.dataModel.item(index) as Entry | FilesAppEntry;
+    if (!entry) {
+      return '';
+    }
+
+    const locationInfo = this.volumeManager_?.getLocationInfo(entry) || null;
+    return getEntryLabel(locationInfo, entry);
+  }
+
+  /**
+   * Render the Size column of the detail table.
+   *
+   * @param entry The Entry object to render.
+   * @param _columnId The id of the column to be rendered.
+   * @param _table The table doing the rendering.
+   * @return Created element.
+   */
+  private renderSize_(entry: Entry, _columnId: string, _table: Table):
+      HTMLDivElement {
+    const div = this.ownerDocument.createElement('div');
+    div.className = 'size';
+    this.updateSize_(div, entry);
+
+    return div;
+  }
+
+  /**
+   * Sets up or updates the size cell.
+   *
+   * @param div The table cell.
+   * @param entry The corresponding entry.
+   */
+  private updateSize_(div: HTMLElement, entry: Entry) {
+    const metadata = this.metadataModel_!.getCache(
+        [entry], ['size', 'hosted', 'contentMimeType'])[0]!;
+    const size = metadata.size;
+    const special = metadata.hosted ||
+        FileType.isEncrypted(entry, metadata.contentMimeType);
+    div.textContent = this.formatter_!.formatSize(size, special);
+  }
+
+  /**
+   * Render the Type column of the detail table.
+   *
+   * @param entry The Entry object to render.
+   * @param _columnId The id of the column to be rendered.
+   * @param _table The table doing the rendering.
+   * @return Created element.
+   */
+  private renderType_(entry: Entry, _columnId: string, _table: Table):
+      HTMLDivElement {
+    const div = this.ownerDocument.createElement('div');
+    div.className = 'type';
+
+    const mimeType =
+        this.metadataModel_!.getCache(
+                                [entry],
+                                ['contentMimeType'])[0]!.contentMimeType;
+    div.textContent =
+        FileListModel.getFileTypeString(FileType.getType(entry, mimeType));
+    return div;
+  }
+
+  /**
+   * Render the Date column of the detail table.
+   *
+   * @param entry The Entry object to render.
+   * @param _columnId The id of the column to be rendered.
+   * @param _table The table doing the rendering.
+   * @return Created element.
+   */
+  private renderDate_(entry: Entry, _columnId: string, _table: Table):
+      HTMLDivElement {
+    const div = this.ownerDocument.createElement('div');
+
+    div.className = 'dateholder';
+    const label = this.ownerDocument.createElement('div');
+    div.appendChild(label);
+    label.className = 'date';
+    this.updateDate_(label, entry);
+    const metadata = this.metadataModel_!.getCache(
+        [entry], ['contentMimeType', 'isDlpRestricted'])[0]!;
+    const isEncrypted = FileType.isEncrypted(entry, metadata.contentMimeType);
+    if (isEncrypted) {
+      div.appendChild(this.renderEncryptedIcon_());
+    }
+    if (isDlpEnabled()) {
+      div.appendChild(this.renderDlpManagedIcon_(!!metadata.isDlpRestricted));
+    }
+    return div;
+  }
+
+  /**
+   * Sets up or updates the date cell.
+   *
+   * @param div The table cell.
+   * @param entry Entry of file to update.
+   */
+  private updateDate_(div: HTMLElement, entry: Entry) {
+    const item = this.metadataModel_!.getCache(
+        [entry], ['modificationTime', 'modificationByMeTime'])[0]!;
+    const modTime = this.useModificationByMeTime_ ?
+        item.modificationByMeTime || item.modificationTime :
+        item.modificationTime;
+
+    div.textContent = this.formatter_!.formatModDate(modTime);
+  }
+
+  private updateGroupHeading_() {
+    const fileListModel = this.dataModel as FileListModel;
+    if (fileListModel &&
+        fileListModel.groupByField === GROUP_BY_FIELD_MODIFICATION_TIME) {
+      // TODO(crbug.com/1353650): find a way to update heading instead of redraw
+      this.redraw();
+    }
+  }
+
+  /**
+   * Updates the file metadata in the table item.
+   *
+   * @param item Table item.
+   * @param entry File entry.
+   */
+  updateFileMetadata(item: HTMLElement, entry: Entry) {
+    this.updateDate_(item.querySelector<HTMLElement>('.date')!, entry);
+    this.updateSize_(item.querySelector<HTMLElement>('.size')!, entry);
+  }
+
+  /**
+   * Updates list items 'in place' on metadata change.
+   * @param type Type of metadata change.
+   * @param entries Entries to update.
+   */
+  updateListItemsMetadata(type: string, entries: Entry[]) {
+    const urls = entriesToURLs(entries);
+    const forEachCell =
+        (selector: string,
+         callback: (cell: HTMLElement, entry: Entry, item: ListItem|null) =>
+             void) => {
+          const cells = this.querySelectorAll<HTMLElement>(selector);
+          for (let i = 0; i < cells.length; i++) {
+            const cell = cells[i]!;
+            const listItem = this.list.getListItemAncestor(cell);
+            const index = listItem?.listIndex ?? 0;
+            const entry = this.dataModel.item(index);
+            if (entry && urls.indexOf(entry.toURL()) !== -1) {
+              callback.call(this, cell, entry, listItem);
+            }
+          }
+        };
+    if (type === 'filesystem') {
+      forEachCell('.table-row-cell .date', (item, entry) => {
+        this.updateDate_(item, entry);
+      });
+      forEachCell('.table-row-cell > .size', (item, entry) => {
+        this.updateSize_(item, entry);
+      });
+      this.updateGroupHeading_();
+    } else if (type === 'external') {
+      // The cell name does not matter as the entire list item is needed.
+      forEachCell(
+          '.table-row-cell .date',
+          (_item: HTMLElement, entry: Entry, listItem: ListItem|null) => {
+            updateListItemExternalProps(
+                listItem!, entry,
+                this.metadataModel_!.getCache(
+                    [entry],
+                    [
+                      'availableOffline',
+                      'customIconUrl',
+                      'shared',
+                      'isMachineRoot',
+                      'isExternalMedia',
+                      'hosted',
+                      'pinned',
+                      'syncStatus',
+                      'progress',
+                      'syncCompletedTime',
+                      'shortcut',
+                      'canPin',
+                      'isDlpRestricted',
+                    ])[0]!,
+                isTeamDriveRoot(entry));
+            listItem!.toggleAttribute(
+                'disabled',
+                isDlpBlocked(
+                    entry, this.metadataModel_!, this.volumeManager_!));
+          });
+    }
+  }
+
+  /**
+   * Renders table row.
+   * @param baseRenderFunction Base renderer.
+   * @param entry Corresponding entry.
+   * @return Created element.
+   */
+  private renderTableRow_(
+      baseRenderFunction: (entry: Entry, table: Table) => ListItem,
+      entry: Entry): ListItem {
+    const item = baseRenderFunction(entry, this);
+    const nameId = item.id + '-entry-name';
+    const sizeId = item.id + '-size';
+    const typeId = item.id + '-type';
+    const dateId = item.id + '-date';
+    const dlpId = item.id + '-dlp-managed-icon';
+    const encryptedId = item.id + '-encrypted-icon';
+    decorateListItem(item, entry, this.metadataModel_!, this.volumeManager_!);
+    item.setAttribute('file-name', entry.name);
+    item.querySelector('.detail-name')!.setAttribute('id', nameId);
+    item.querySelector('.size')!.setAttribute('id', sizeId);
+    item.querySelector('.type')!.setAttribute('id', typeId);
+    item.querySelector('.date')!.setAttribute('id', dateId);
+    const dlpManagedIcon = item.querySelector('.dlp-managed-icon');
+    if (dlpManagedIcon) {
+      dlpManagedIcon.setAttribute('id', dlpId);
+      this.ownerDocument.querySelector('files-tooltip')!.addTargets(
+          item.querySelectorAll('.dlp-managed-icon'));
+    }
+    const encryptedIcon = item.querySelector('.encrypted-icon');
+    if (encryptedIcon) {
+      encryptedIcon.setAttribute('id', encryptedId);
+    }
+
+    item.setAttribute(
+        'aria-labelledby',
+        `${nameId} column-size ${sizeId} column-type ${
+            typeId} column-modificationTime ${dateId} ${encryptedId}`);
+    return item;
+  }
+
+  /**
+   * Renders the file thumbnail in the detail table.
+   * @param entry The Entry object to render.
+   * @param parent The parent DOM element.
+   * @return Created element.
+   */
+  private renderThumbnail_(entry: Entry, parent: HTMLDivElement):
+      HTMLDivElement {
+    const box = this.ownerDocument.createElement('div');
+    box.className = 'detail-thumbnail';
+
+    // Set thumbnail if it's already in cache.
+    const thumbnailData = this.listThumbnailLoader_ ?
+        this.listThumbnailLoader_.getThumbnailFromCache(entry) :
+        null;
+    if (thumbnailData && thumbnailData.dataUrl) {
+      this.setThumbnailImage_(box, thumbnailData.dataUrl);
+      parent.classList.add('has-thumbnail');
+    }
+
+    return box;
+  }
+
+  /**
+   * Sets thumbnail image to the box.
+   * @param box Detail thumbnail div element.
+   * @param dataUrl Data url of thumbnail.
+   */
+  private setThumbnailImage_(box: HTMLDivElement, dataUrl: string) {
+    const thumbnail = box.ownerDocument.createElement('div');
+    thumbnail.classList.add('thumbnail');
+    thumbnail.style.backgroundImage = 'url(' + dataUrl + ')';
+    const oldThumbnails = box.querySelectorAll('.thumbnail');
+
+    for (let i = 0; i < oldThumbnails.length; i++) {
+      box.removeChild(oldThumbnails[i]!);
+    }
+
+    box.appendChild(thumbnail);
+  }
+
+  /**
+   * Clears thumbnail image from the box.
+   * @param box Detail thumbnail div element.
+   */
+  private clearThumbnailImage_(box: HTMLDivElement) {
+    const oldThumbnails = box.querySelectorAll('.thumbnail');
+
+    for (let i = 0; i < oldThumbnails.length; i++) {
+      box.removeChild(oldThumbnails[i]!);
+    }
+  }
+
+  /**
+   * Renders the selection checkmark in the detail table.
+   * @return Created element.
+   */
+  private renderCheckmark_(): HTMLDivElement {
+    const checkmark = this.ownerDocument.createElement('div');
+    checkmark.className = 'detail-checkmark';
+    return checkmark;
+  }
+
+  /**
+   * Renders the DLP managed icon in the detail table.
+   * @param isDlpRestricted Whether the icon should be shown.
+   * @return Created element.
+   */
+  private renderDlpManagedIcon_(isDlpRestricted: boolean): HTMLDivElement {
+    const icon = this.ownerDocument.createElement('div');
+    icon.className = 'dlp-managed-icon';
+    icon.toggleAttribute('has-tooltip');
+    icon.dataset['tooltipLinkHref'] = str('DLP_HELP_URL');
+    icon.dataset['tooltipLinkAriaLabel'] = str('DLP_MANAGED_ICON_TOOLTIP_DESC');
+    icon.dataset['tooltipLinkText'] = str('DLP_MANAGED_ICON_TOOLTIP_LINK');
+    icon.setAttribute('aria-label', str('DLP_MANAGED_ICON_TOOLTIP'));
+    icon.toggleAttribute('show-card-tooltip');
+    icon.classList.toggle('is-dlp-restricted', isDlpRestricted);
+    icon.toggleAttribute('aria-hidden', isDlpRestricted);
+    return icon;
+  }
+
+  /**
+   * Renders the encrypted icon in the detail table, used to mark Google Drive
+   * CSE files.
+   * @return Created element.
+   */
+  private renderEncryptedIcon_(): HTMLDivElement {
+    const icon = this.ownerDocument.createElement('div');
+    icon.className = 'encrypted-icon';
+    icon.setAttribute('aria-label', str('ENCRYPTED_ICON_TOOLTIP'));
+    document.querySelector('files-tooltip')?.addTarget(icon);
+    return icon;
+  }
+
+  /**
+   * Redraws the UI. Skips multiple consecutive calls.
+   */
+  relayout() {
+    this.relayoutRateLimiter_!.run();
+  }
+
+  /**
+   * Redraws the UI immediately.
+   */
+  private relayoutImmediately_() {
+    if (this.clientWidth > 0) {
+      this.normalizeColumns();
+    }
+    this.redraw();
+    dispatchSimpleEvent(this.list, 'relayout');
+  }
+}
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.ts b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.ts
index 65089d2..e0097b12 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.ts
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.ts
@@ -38,6 +38,7 @@
  */
 export class FileTableList extends TableList {
   private onMergeItems_: null|OnMergeItemsCallback = null;
+  shouldStartDragSelection: null|((e: MouseEvent) => boolean) = null;
 
   constructor() {
     // To silence closure compiler.
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.js
index dcad9c5..435f721 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.js
@@ -4,7 +4,7 @@
 
 import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
-import {FileTableColumnModel} from './file_table.js';
+import {FileTableColumnModel, MIN_WIDTH} from './file_table.js';
 import {TableColumn} from './table/table_column.js';
 
 /** @type {!FileTableColumnModel} */
@@ -228,7 +228,7 @@
 
   // Should keep the minimum width.
   getColumnWidths(model).map(width => {
-    assertEquals(FileTableColumnModel.MIN_WIDTH_, width);
+    assertEquals(MIN_WIDTH, width);
   });
 }
 
@@ -241,11 +241,10 @@
 
   // Should keep the minimum width.
   getColumnWidths(model).map(width => {
-    assertTrue(width >= FileTableColumnModel.MIN_WIDTH_);
+    assertTrue(width >= MIN_WIDTH);
   });
-  const minWidth = FileTableColumnModel.MIN_WIDTH_;
   // Total width = 500.
   const expectedWidths =
-      [100, 100, 500 - 100 * 2 - minWidth * 2, minWidth, minWidth];
+      [100, 100, 500 - 100 * 2 - MIN_WIDTH * 2, MIN_WIDTH, MIN_WIDTH];
   assertArrayEquals(expectedWidths, getColumnWidths(model));
 }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/list.ts b/ui/file_manager/file_manager/foreground/js/ui/list.ts
index 6b7233f..2c50b5c 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/list.ts
+++ b/ui/file_manager/file_manager/foreground/js/ui/list.ts
@@ -135,6 +135,8 @@
   private boundHandleLeadChange_: EventHandler|null = null;
   protected beforeFiller_: HTMLElement|null = null;
   protected afterFiller_: HTMLElement|null = null;
+  /** Managed by DragSelector */
+  cachedBounds: DOMRect|null = null;
 
   /**
    * Function used to create grid items.
diff --git a/ui/file_manager/file_manager/foreground/js/ui/table/table.ts b/ui/file_manager/file_manager/foreground/js/ui/table/table.ts
index 1cd8224..c5f0a01 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/table/table.ts
+++ b/ui/file_manager/file_manager/foreground/js/ui/table/table.ts
@@ -137,7 +137,7 @@
    * Returns render function for row.
    * @return Render function.
    */
-  getRenderFunction(): (_: unknown, _t: Table) => HTMLElement {
+  getRenderFunction(): (_: unknown, _t: Table) => ListItem {
     return this.renderFunction_;
   }
 
@@ -158,7 +158,7 @@
       }
       cell.hidden = !cm.isVisible(i);
       cell.appendChild(
-          cm.getRenderFunction(i).call(null, dataItem, cm.getId(i), table));
+          cm.getRenderFunction(i).call(null, dataItem, cm.getId(i)!, table));
 
       listItem.appendChild(cell);
     }
@@ -169,10 +169,9 @@
 
   /**
    * Sets render function for row.
-   * @param renderFunction Render
-   *     function.
+   * @param renderFunction Render function.
    */
-  setRenderFunction(renderFunction: (_: unknown, _t: Table) => ListItem) {
+  setRenderFunction(renderFunction: (_item: any, _t: Table) => ListItem) {
     if (renderFunction === this.renderFunction_) {
       return;
     }
@@ -192,7 +191,7 @@
   /**
    * Initializes the element.
    */
-  static decorate(element: Element) {
+  static decorate(element: Element, ..._: any[]) {
     Object.setPrototypeOf(element, Table.prototype);
     const table = element as Table;
 
@@ -327,7 +326,7 @@
       const sortDirection = sortStatus.direction == 'desc' ? 'asc' : 'desc';
       this.list.dataModel!.sort(sortStatus.field, sortDirection);
     } else {
-      this.list.dataModel!.sort(cm.getId(i), cm.getDefaultOrder(i));
+      this.list.dataModel!.sort(cm.getId(i)!, cm.getDefaultOrder(i));
     }
     if (this.selectionModel.selectedIndex == -1) {
       this.list.scrollTop = 0;
@@ -378,7 +377,7 @@
 
     const cm = this.columnModel_!;
     const dm = this.dataModel;
-    const columnId = cm.getId(index);
+    const columnId = cm.getId(index)!;
     const doc = this.ownerDocument;
     const render = cm.getRenderFunction(index);
     const table = this;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/table/table_column.ts b/ui/file_manager/file_manager/foreground/js/ui/table/table_column.ts
index 0c14069..41c42d9 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/table/table_column.ts
+++ b/ui/file_manager/file_manager/foreground/js/ui/table/table_column.ts
@@ -11,8 +11,9 @@
 
 import {jsSetter} from '../../../../common/js/cr_ui.js';
 
-export type RenderFunction = (_1: unknown, _2: string, _3: Element) =>
-    HTMLElement;
+import type {Table} from './table.js';
+
+export type RenderFunction = (_1: any, _2: string, _3: Table) => HTMLElement;
 
 export type SortDirection = 'asc'|'desc';
 /**
diff --git a/ui/file_manager/file_manager/foreground/js/ui/table/table_column_model.ts b/ui/file_manager/file_manager/foreground/js/ui/table/table_column_model.ts
index ace29c1d..bf357025 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/table/table_column_model.ts
+++ b/ui/file_manager/file_manager/foreground/js/ui/table/table_column_model.ts
@@ -43,8 +43,8 @@
    * @param index The index of the column.
    * @return Column id.
    */
-  getId(index: number): string {
-    return this.columns_[index]?.id ?? '';
+  getId(index: number): string|undefined {
+    return this.columns_[index]?.id;
   }
 
   /**
diff --git a/ui/file_manager/file_manager/foreground/js/ui/table/table_header.ts b/ui/file_manager/file_manager/foreground/js/ui/table/table_header.ts
index 7ff27bea..489b0b61 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/table/table_header.ts
+++ b/ui/file_manager/file_manager/foreground/js/ui/table/table_header.ts
@@ -116,7 +116,7 @@
       cell.hidden = !cm.isVisible(i);
       cell.className = 'table-header-cell';
       const tableHeader = this;
-      if (dm.isSortable(cm.getId(i))) {
+      if (dm.isSortable(cm.getId(i)!)) {
         cell.addEventListener(
             'click', this.createSortFunction_(i).bind(tableHeader));
       }
@@ -176,7 +176,7 @@
 
     const labelDiv = this.ownerDocument.createElement('div');
     labelDiv.className = 'table-header-label';
-    labelDiv.classList.add(cm.getId(index));
+    labelDiv.classList.add(cm.getId(index)!);
 
     if (cm.isEndAlign(index)) {
       labelDiv.style.textAlign = 'end';
diff --git a/ui/file_manager/file_names.gni b/ui/file_manager/file_names.gni
index 1893ab4..000dc14 100644
--- a/ui/file_manager/file_names.gni
+++ b/ui/file_manager/file_names.gni
@@ -151,7 +151,6 @@
   "file_manager/foreground/js/ui/file_manager_dialog_base.js",
   "file_manager/foreground/js/ui/file_manager_ui.js",
   "file_manager/foreground/js/ui/file_metadata_formatter.js",
-  "file_manager/foreground/js/ui/file_table.js",
   "file_manager/foreground/js/ui/file_tap_handler.js",
   "file_manager/foreground/js/ui/files_alert_dialog.js",
   "file_manager/foreground/js/ui/files_confirm_dialog.js",
@@ -253,6 +252,7 @@
 
   # Foreground UI.
   "file_manager/foreground/js/ui/file_grid.ts",
+  "file_manager/foreground/js/ui/file_table.ts",
   "file_manager/foreground/js/ui/file_table_list.ts",
   "file_manager/foreground/js/ui/grid.ts",
   "file_manager/foreground/js/ui/list.ts",
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
index e8867140..95ade02 100644
--- a/ui/gfx/render_text_harfbuzz.cc
+++ b/ui/gfx/render_text_harfbuzz.cc
@@ -434,11 +434,11 @@
 
   size_t ApplyWhitespaceElisionBackward(size_t index) {
     // This function removes unnecessary whitespace. For example, without
-    // this function, elide_tail could turn a string:"abc  x" to "abc  Â…".
+    // this function, elide_tail could turn a string:"abc  x" to "abc  ...".
     // While the result is valid if it fits the display rect, there
     // is no need to have whitespace between the elide codepoint and the rest of
     // the string. Enabling ApplyWhitespaceElisionBackward will reduce the index
-    // such that resulting string is "abcÂ…".
+    // such that resulting string is "abc...".
     if (!render_text()->whitespace_elision().has_value() ||
         render_text()->whitespace_elision().value()) {
       while (index > 0 && render_text()->text()[index - 1] == ' ') {
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index 23e9f91..e45d1a2 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -3,8 +3,8 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
+import("//build/config/cast.gni")
 import("//build/config/chrome_build.gni")
-import("//build/config/chromecast_build.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/linux/pkg_config.gni")
 import("//build/config/ozone.gni")
diff --git a/ui/gl/features.gni b/ui/gl/features.gni
index 8326661..10917487 100644
--- a/ui/gl/features.gni
+++ b/ui/gl/features.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//chrome/version.gni")
diff --git a/ui/gtk/printing/print_dialog_gtk.cc b/ui/gtk/printing/print_dialog_gtk.cc
index 525df2c..9d91474 100644
--- a/ui/gtk/printing/print_dialog_gtk.cc
+++ b/ui/gtk/printing/print_dialog_gtk.cc
@@ -456,16 +456,13 @@
 void PrintDialogGtk::PrintDocument(const printing::MetafilePlayer& metafile,
                                    const std::u16string& document_name) {
 #if DCHECK_IS_ON()
-#if BUILDFLAG(ENABLE_OOP_PRINTING)
-  const bool kOopPrinting = printing::features::ShouldPrintJobOop();
-#else
-  const bool kOopPrinting = false;
-#endif  // BUILDFLAG(ENABLE_OOP_PRINTING)
+  bool oop_printing = context_->process_behavior() !=
+                      printing::PrintingContext::ProcessBehavior::kOopDisabled;
 
   // For in-browser printing, this runs on the print worker thread, so it does
   // not block the UI thread.  For OOP it runs on the service document task
   // runner.
-  DCHECK_EQ(owning_task_runner()->RunsTasksInCurrentSequence(), kOopPrinting);
+  DCHECK_EQ(owning_task_runner()->RunsTasksInCurrentSequence(), oop_printing);
 #endif  // DCHECK_IS_ON()
 
   // The document printing tasks can outlive the PrintingContext that created
diff --git a/ui/lottie/animation.cc b/ui/lottie/animation.cc
index ee0145e..59a0531 100644
--- a/ui/lottie/animation.cc
+++ b/ui/lottie/animation.cc
@@ -256,6 +256,9 @@
 void Animation::Stop() {
   state_ = PlayState::kStopped;
   timer_control_.reset(nullptr);
+  for (AnimationObserver& obs : observers_) {
+    obs.AnimationStopped(this);
+  }
 }
 
 absl::optional<float> Animation::GetCurrentProgress() const {
diff --git a/ui/lottie/animation_observer.h b/ui/lottie/animation_observer.h
index a0e8bcd..8146ee0 100644
--- a/ui/lottie/animation_observer.h
+++ b/ui/lottie/animation_observer.h
@@ -32,6 +32,9 @@
   // |t| is the normalized timestamp in range [0, 1] of the frame just painted.
   virtual void AnimationFramePainted(const Animation* animation, float t) {}
 
+  // Called when the animation is `Stop()`ed.
+  virtual void AnimationStopped(const Animation* animation) {}
+
   // Called in the Animation's destructor. Observers may remove themselves
   // within their implementation.
   virtual void AnimationIsDeleting(const Animation* animation) {}
diff --git a/ui/lottie/animation_unittest.cc b/ui/lottie/animation_unittest.cc
index 77c0869..417d312 100644
--- a/ui/lottie/animation_unittest.cc
+++ b/ui/lottie/animation_unittest.cc
@@ -114,6 +114,10 @@
     last_frame_painted_ = t;
   }
 
+  void AnimationStopped(const Animation* animation) override {
+    animation_stopped_ = true;
+  }
+
   void AnimationIsDeleting(const Animation* animation) override {
     animation_is_deleted_ = true;
     observation_.Reset();
@@ -130,6 +134,7 @@
     return animation_will_start_playing_;
   }
   bool animation_resuming() const { return animation_resuming_; }
+  bool animation_stopped() const { return animation_stopped_; }
   bool animation_is_deleted() const { return animation_is_deleted_; }
   const absl::optional<float>& last_frame_painted() const {
     return last_frame_painted_;
@@ -141,6 +146,7 @@
   bool animation_will_start_playing_ = false;
   bool animation_resuming_ = false;
   bool animation_is_deleted_ = false;
+  bool animation_stopped_ = false;
   absl::optional<float> last_frame_painted_;
 };
 
@@ -417,7 +423,9 @@
   EXPECT_FLOAT_EQ(*animation_->GetCurrentProgress(),
                   kAdvance / kAnimationDuration);
 
+  EXPECT_FALSE(observer.animation_stopped());
   animation_->Stop();
+  EXPECT_TRUE(observer.animation_stopped());
   EXPECT_FALSE(animation_->GetCurrentProgress());
   EXPECT_TRUE(IsStopped());
 }
diff --git a/ui/native_theme/overlay_scrollbar_constants_aura.h b/ui/native_theme/overlay_scrollbar_constants_aura.h
index e809563f..26646147 100644
--- a/ui/native_theme/overlay_scrollbar_constants_aura.h
+++ b/ui/native_theme/overlay_scrollbar_constants_aura.h
@@ -21,6 +21,15 @@
 constexpr base::TimeDelta kOverlayScrollbarThinningDuration =
     base::Milliseconds(200);
 
+// Fluent Overlay scrollbars animation times are modified to align with
+// Windows' 11 Fluent Design language.
+constexpr base::TimeDelta kFluentOverlayScrollbarFadeDelay =
+    base::Milliseconds(750);
+constexpr base::TimeDelta kFluentOverlayScrollbarFadeDuration =
+    base::Milliseconds(100);
+constexpr base::TimeDelta kFluentOverlayScrollbarThinningDuration =
+    base::Milliseconds(100);
+
 }  // namespace ui
 
 #endif  // UI_NATIVE_THEME_OVERLAY_SCROLLBAR_CONSTANTS_AURA_H_
diff --git a/ui/ozone/platform/cast/BUILD.gn b/ui/ozone/platform/cast/BUILD.gn
index 0dd7c78..0051137 100644
--- a/ui/ozone/platform/cast/BUILD.gn
+++ b/ui/ozone/platform/cast/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/ozone.gni")
 
 visibility = [
diff --git a/ui/ozone/platform/drm/BUILD.gn b/ui/ozone/platform/drm/BUILD.gn
index f16f204..71a8ae46 100644
--- a/ui/ozone/platform/drm/BUILD.gn
+++ b/ui/ozone/platform/drm/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/linux/pkg_config.gni")
 import("//build/config/logging.gni")
diff --git a/ui/ozone/platform/wayland/common/wayland_util.cc b/ui/ozone/platform/wayland/common/wayland_util.cc
index dc02f56..63a23190 100644
--- a/ui/ozone/platform/wayland/common/wayland_util.cc
+++ b/ui/ozone/platform/wayland/common/wayland_util.cc
@@ -6,9 +6,11 @@
 
 #include <xdg-shell-client-protocol.h>
 
+#include "build/buildflag.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "third_party/skia/include/core/SkRegion.h"
 #include "ui/base/hit_test.h"
+#include "ui/events/base_event_utils.h"
 #include "ui/gfx/geometry/skia_conversions.h"
 #include "ui/gfx/geometry/transform.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
@@ -332,4 +334,15 @@
   }
 }
 
+base::TimeTicks EventMillisecondsToTimeTicks(uint32_t milliseconds) {
+#if BUILDFLAG(IS_LINUX)
+  // TODO(crbug.com/1499638): `milliseconds` comes from Weston that
+  // uses timestamp from libinput, which is different from TimeTicks.
+  // Use EventTimeForNow(), for now.
+  return ui::EventTimeForNow();
+#else
+  return base::TimeTicks() + base::Milliseconds(milliseconds);
+#endif
+}
+
 }  // namespace wl
diff --git a/ui/ozone/platform/wayland/common/wayland_util.h b/ui/ozone/platform/wayland/common/wayland_util.h
index e62d04c3..8570f22 100644
--- a/ui/ozone/platform/wayland/common/wayland_util.h
+++ b/ui/ozone/platform/wayland/common/wayland_util.h
@@ -10,6 +10,7 @@
 #include "base/containers/flat_map.h"
 #include "base/files/scoped_file.h"
 #include "base/functional/callback.h"
+#include "base/time/time.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/rect.h"
@@ -119,6 +120,9 @@
     const absl::variant<gfx::OverlayTransform, gfx::Transform>& transform,
     wl_array& array);
 
+// Converts `milliseconds`, which is server dependent, to base::TimeTicks.
+base::TimeTicks EventMillisecondsToTimeTicks(uint32_t milliseconds);
+
 }  // namespace wl
 
 #endif  // UI_OZONE_PLATFORM_WAYLAND_COMMON_WAYLAND_UTIL_H_
diff --git a/ui/ozone/platform/wayland/host/wayland_clipboard.cc b/ui/ozone/platform/wayland/host/wayland_clipboard.cc
index 8cd9f6f4..f1826e8 100644
--- a/ui/ozone/platform/wayland/host/wayland_clipboard.cc
+++ b/ui/ozone/platform/wayland/host/wayland_clipboard.cc
@@ -175,7 +175,9 @@
   }
 
   // WaylandDataSource::Delegate:
-  void OnDataSourceFinish(DataSource* source, bool completed) override {
+  void OnDataSourceFinish(DataSource* source,
+                          base::TimeTicks timestamp,
+                          bool completed) override {
     if (!completed)
       Write(nullptr);
   }
diff --git a/ui/ozone/platform/wayland/host/wayland_data_device.cc b/ui/ozone/platform/wayland/host/wayland_data_device.cc
index 86e20cbd..3948c6e 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_device.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_device.cc
@@ -12,6 +12,7 @@
 #include "base/functional/bind.h"
 #include "base/logging.h"
 #include "build/chromeos_buildflags.h"
+#include "ui/events/base_event_utils.h"
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/ozone/platform/wayland/common/wayland_object.h"
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
@@ -133,6 +134,8 @@
     VLOG(1) << "Failed to get window.";
     return;
   }
+  // drag enter event doesn't have timestamp. Use EventTimeForNow().
+  const auto timestamp = EventTimeForNow();
 
   // Null |drag_delegate_| here means that the DND session has been initiated by
   // an external application. In this case, use the default data drag delegate.
@@ -144,7 +147,7 @@
 
   gfx::PointF point = self->connection()->MaybeConvertLocation(
       gfx::PointF(wl_fixed_to_double(x), wl_fixed_to_double(y)), window);
-  self->drag_delegate_->OnDragEnter(window, point, serial);
+  self->drag_delegate_->OnDragEnter(window, point, timestamp, serial);
 
   self->connection()->Flush();
 }
@@ -159,14 +162,17 @@
     gfx::PointF point = self->connection()->MaybeConvertLocation(
         gfx::PointF(wl_fixed_to_double(x), wl_fixed_to_double(y)),
         self->drag_delegate_->GetDragTarget());
-    self->drag_delegate_->OnDragMotion(point);
+    self->drag_delegate_->OnDragMotion(point,
+                                       wl::EventMillisecondsToTimeTicks(time));
   }
 }
 
 void WaylandDataDevice::OnDrop(void* data, wl_data_device* data_device) {
+  // drop event doesn't have timestamp. Use EventTimeForNow().
+  const auto timestamp = EventTimeForNow();
   auto* self = static_cast<WaylandDataDevice*>(data);
   if (self->drag_delegate_) {
-    self->drag_delegate_->OnDragDrop();
+    self->drag_delegate_->OnDragDrop(timestamp);
     self->connection()->Flush();
   }
 
@@ -175,15 +181,17 @@
   // potential leaks and/or UAFs, forcibly call corresponding delegate callback
   // here, in Lacros. TODO(crbug.com/1293415): Remove once Exo bug is fixed.
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-  self->drag_delegate_->OnDragLeave();
+  self->drag_delegate_->OnDragLeave(timestamp);
   self->ResetDragDelegateIfNotDragSource();
 #endif
 }
 
 void WaylandDataDevice::OnLeave(void* data, wl_data_device* data_device) {
+  // leave event doesn't have timestamp. Use EventTimeForNow().
+  const auto timestamp = EventTimeForNow();
   auto* self = static_cast<WaylandDataDevice*>(data);
   if (self->drag_delegate_) {
-    self->drag_delegate_->OnDragLeave();
+    self->drag_delegate_->OnDragLeave(timestamp);
     self->connection()->Flush();
   }
   self->ResetDragDelegateIfNotDragSource();
diff --git a/ui/ozone/platform/wayland/host/wayland_data_device.h b/ui/ozone/platform/wayland/host/wayland_data_device.h
index ad63bf6..06596e3 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_device.h
+++ b/ui/ozone/platform/wayland/host/wayland_data_device.h
@@ -42,10 +42,12 @@
     virtual void OnDragOffer(std::unique_ptr<WaylandDataOffer> offer) = 0;
     virtual void OnDragEnter(WaylandWindow* window,
                              const gfx::PointF& location,
+                             base::TimeTicks timestamp,
                              uint32_t serial) = 0;
-    virtual void OnDragMotion(const gfx::PointF& location) = 0;
-    virtual void OnDragLeave() = 0;
-    virtual void OnDragDrop() = 0;
+    virtual void OnDragMotion(const gfx::PointF& location,
+                              base::TimeTicks timestamp) = 0;
+    virtual void OnDragLeave(base::TimeTicks timestamp) = 0;
+    virtual void OnDragDrop(base::TimeTicks timestamp) = 0;
 
     virtual const WaylandWindow* GetDragTarget() const = 0;
 
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
index b1e973a..1e7dc8f 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
@@ -21,6 +21,7 @@
 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/base/dragdrop/os_exchange_data_provider_non_backed.h"
+#include "ui/events/base_event_utils.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/events/platform/scoped_event_dispatcher.h"
@@ -337,6 +338,7 @@
 
 void WaylandDataDragController::OnDragEnter(WaylandWindow* window,
                                             const gfx::PointF& location,
+                                            base::TimeTicks timestamp,
                                             uint32_t serial) {
   DCHECK(window);
   DCHECK(data_offer_);
@@ -358,7 +360,7 @@
     DCHECK(drag_source_.has_value());
     if (*drag_source_ == DragEventSource::kMouse) {
       pointer_delegate_->OnPointerFocusChanged(
-          window, location, wl::EventDispatchPolicy::kImmediate);
+          window, location, timestamp, wl::EventDispatchPolicy::kImmediate);
     } else {
       touch_delegate_->OnTouchFocusChanged(window);
     }
@@ -373,7 +375,7 @@
     // |offered_exchange_data_provider_| already holds the data to be exchanged,
     // so we don't need to read it through Wayland and can just copy it here.
     DCHECK(offered_exchange_data_provider_);
-    PropagateOnDragEnter(location,
+    PropagateOnDragEnter(location, timestamp,
                          std::make_unique<OSExchangeData>(
                              offered_exchange_data_provider_->Clone()));
   } else {
@@ -385,11 +387,12 @@
     received_exchange_data_provider_ =
         std::make_unique<WaylandExchangeDataProvider>();
     last_drag_location_ = location;
-    HandleUnprocessedMimeTypes(base::TimeTicks::Now());
+    HandleUnprocessedMimeTypes(timestamp);
   }
 }
 
-void WaylandDataDragController::OnDragMotion(const gfx::PointF& location) {
+void WaylandDataDragController::OnDragMotion(const gfx::PointF& location,
+                                             base::TimeTicks timestamp) {
   VLOG(2) << __FUNCTION__ << " window=" << !!window_
           << " location=" << location.ToString()
           << " transferring=" << (state_ == State::kTransferring);
@@ -411,7 +414,7 @@
   data_offer_->SetDndActions(DragOperationsToDndActions(client_operations));
 }
 
-void WaylandDataDragController::OnDragLeave() {
+void WaylandDataDragController::OnDragLeave(base::TimeTicks timestamp) {
   VLOG(2) << __FUNCTION__ << " window=" << !!window_
           << " transferring=" << (state_ == State::kTransferring);
 
@@ -430,7 +433,7 @@
   is_leave_pending_ = false;
 }
 
-void WaylandDataDragController::OnDragDrop() {
+void WaylandDataDragController::OnDragDrop(base::TimeTicks timestamp) {
   VLOG(1) << __FUNCTION__ << " window=" << !!window_;
   if (!window_) {
     return;
@@ -446,6 +449,7 @@
 }
 
 void WaylandDataDragController::OnDataSourceFinish(WaylandDataSource* source,
+                                                   base::TimeTicks timestamp,
                                                    bool completed) {
   CHECK_EQ(data_source_.get(), source);
   VLOG(1) << __FUNCTION__ << " window=" << !!window_
@@ -472,7 +476,7 @@
   // extra leave event that is dispatched if |completed| is false may cause
   // problems.
   if (pointer_grabber_for_window_drag_) {
-    DispatchPointerRelease();
+    DispatchPointerRelease(timestamp);
   }
 
   data_source_.reset();
@@ -554,7 +558,7 @@
 }
 
 void WaylandDataDragController::OnMimeTypeDataTransferred(
-    base::TimeTicks start_time,
+    base::TimeTicks timestamp,
     PlatformClipboard::Data contents) {
   DCHECK(contents);
   std::string mime_type = unprocessed_mime_types_.front();
@@ -566,11 +570,11 @@
   RunDataTransferredCallbackForTesting(mime_type);  // IN-TEST
 
   // Continue reading data for other negotiated mime types.
-  HandleUnprocessedMimeTypes(start_time);
+  HandleUnprocessedMimeTypes(timestamp);
 }
 
 void WaylandDataDragController::OnDataTransferFinished(
-    base::TimeTicks start_time,
+    base::TimeTicks timestamp,
     std::unique_ptr<OSExchangeData> received_data) {
   VLOG(1) << __FUNCTION__ << " unprocessed=" << unprocessed_mime_types_.size()
           << " leave_pending=" << is_leave_pending_ << " window=" << !!window_;
@@ -599,9 +603,10 @@
   }
 
   UMA_HISTOGRAM_TIMES("Event.WaylandDragDrop.IncomingDataTransferTime",
-                      base::TimeTicks::Now() - start_time);
+                      base::TimeTicks::Now() - timestamp);
 
-  PropagateOnDragEnter(last_drag_location_, std::move(received_data));
+  PropagateOnDragEnter(last_drag_location_, timestamp,
+                       std::move(received_data));
 }
 
 // Returns the next MIME type to be received from the source process, or an
@@ -621,6 +626,7 @@
 
 void WaylandDataDragController::PropagateOnDragEnter(
     const gfx::PointF& location,
+    base::TimeTicks timestamp,
     std::unique_ptr<OSExchangeData> data) {
   VLOG(1) << __func__ << " window=" << !!window_ << " offer=" << !!data_offer_;
 
@@ -640,7 +646,7 @@
   window_->OnDragEnter(
       location, std::move(data),
       DndActionsToDragOperations(data_offer_->source_actions()));
-  OnDragMotion(location);
+  OnDragMotion(location, timestamp);
 }
 
 absl::optional<wl::Serial>
@@ -691,11 +697,12 @@
   pointer_grabber_for_window_drag_ = origin_window_;
 }
 
-void WaylandDataDragController::DispatchPointerRelease() {
+void WaylandDataDragController::DispatchPointerRelease(
+    base::TimeTicks timestamp) {
   DCHECK(pointer_grabber_for_window_drag_);
   pointer_delegate_->OnPointerButtonEvent(
-      ET_MOUSE_RELEASED, EF_LEFT_MOUSE_BUTTON, pointer_grabber_for_window_drag_,
-      wl::EventDispatchPolicy::kImmediate,
+      ET_MOUSE_RELEASED, EF_LEFT_MOUSE_BUTTON, timestamp,
+      pointer_grabber_for_window_drag_, wl::EventDispatchPolicy::kImmediate,
       /*allow_release_of_unpressed_button=*/true);
   pointer_grabber_for_window_drag_ = nullptr;
 }
@@ -716,7 +723,8 @@
   // that, for now, is to monitor wl_pointer events here and abort the session
   // if it comes in.
   if (event->type() == ET_MOUSE_RELEASED) {
-    OnDataSourceFinish(data_source_.get(), /*completed=*/false);
+    OnDataSourceFinish(data_source_.get(), event->time_stamp(),
+                       /*completed=*/false);
   }
 
   return POST_DISPATCH_PERFORM_DEFAULT;
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
index 82f72a5..71398bb0 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
+++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
@@ -142,14 +142,18 @@
   void OnDragOffer(std::unique_ptr<WaylandDataOffer> offer) override;
   void OnDragEnter(WaylandWindow* window,
                    const gfx::PointF& location,
+                   base::TimeTicks timestamp,
                    uint32_t serial) override;
-  void OnDragMotion(const gfx::PointF& location) override;
-  void OnDragLeave() override;
-  void OnDragDrop() override;
+  void OnDragMotion(const gfx::PointF& location,
+                    base::TimeTicks timestamp) override;
+  void OnDragLeave(base::TimeTicks timestamp) override;
+  void OnDragDrop(base::TimeTicks timestamp) override;
   const WaylandWindow* GetDragTarget() const override;
 
   // WaylandDataSource::Delegate:
-  void OnDataSourceFinish(WaylandDataSource* source, bool completed) override;
+  void OnDataSourceFinish(WaylandDataSource* source,
+                          base::TimeTicks timestamp,
+                          bool completed) override;
   void OnDataSourceSend(WaylandDataSource* source,
                         const std::string& mime_type,
                         std::string* contents) override;
@@ -167,6 +171,7 @@
   // Calls the window's OnDragEnter with the given location and data,
   // then immediately calls OnDragMotion to get the actual operation.
   void PropagateOnDragEnter(const gfx::PointF& location,
+                            base::TimeTicks timestamp,
                             std::unique_ptr<OSExchangeData> data);
 
   absl::optional<wl::Serial> GetAndValidateSerialForDrag(
@@ -187,7 +192,7 @@
   // Sends an ET_MOUSE_RELEASED event to the window that currently has capture.
   // Must only be called if |pointer_grabber_for_window_drag_| is valid. This
   // resets |pointer_grabber_for_window_drag_|.
-  void DispatchPointerRelease();
+  void DispatchPointerRelease(base::TimeTicks timestamp);
 
   // PlatformEventDispatcher:
   bool CanDispatchEvent(const PlatformEvent& event) override;
diff --git a/ui/ozone/platform/wayland/host/wayland_data_source.cc b/ui/ozone/platform/wayland/host/wayland_data_source.cc
index 67bb981..5a4e53468 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_source.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_source.cc
@@ -13,6 +13,7 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/events/base_event_utils.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
 
 namespace wl {
@@ -38,7 +39,8 @@
 template <typename T>
 void DataSource<T>::HandleFinishEvent(bool completed) {
   VLOG(1) << "OnDataSourceFinish in WaylandDataSource";
-  delegate_->OnDataSourceFinish(this, completed);
+  // No timestamp for these events. Use EventTimeForNow(), for now.
+  delegate_->OnDataSourceFinish(this, ui::EventTimeForNow(), completed);
 }
 
 // Writes |data_str| to file descriptor |fd| assuming it is flagged as
diff --git a/ui/ozone/platform/wayland/host/wayland_data_source.h b/ui/ozone/platform/wayland/host/wayland_data_source.h
index faeceb1..53c74cb 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_source.h
+++ b/ui/ozone/platform/wayland/host/wayland_data_source.h
@@ -17,6 +17,10 @@
 struct gtk_primary_selection_source;
 struct zwp_primary_selection_source_v1;
 
+namespace base {
+class TimeTicks;
+}
+
 namespace wl {
 template <typename T>
 class DataSource;
@@ -54,7 +58,9 @@
  public:
   class Delegate {
    public:
-    virtual void OnDataSourceFinish(DataSource<T>* source, bool completed) = 0;
+    virtual void OnDataSourceFinish(DataSource<T>* source,
+                                    base::TimeTicks timestamp,
+                                    bool completed) = 0;
     virtual void OnDataSourceSend(DataSource<T>* source,
                                   const std::string& mime_type,
                                   std::string* contents) = 0;
diff --git a/ui/ozone/platform/wayland/host/wayland_event_source.cc b/ui/ozone/platform/wayland/host/wayland_event_source.cc
index a747555..922b43a 100644
--- a/ui/ozone/platform/wayland/host/wayland_event_source.cc
+++ b/ui/ozone/platform/wayland/host/wayland_event_source.cc
@@ -162,6 +162,11 @@
   if (axis_source) {
     out << "axis_source=" << *axis_source;
   }
+  if (timestamp) {
+    out << ", timestamp=" << *timestamp;
+  } else {
+    out << ", no timestamp";
+  }
   out << ", d=(" << dx << ", " << dy << "), dt=" << dt
       << ", is_axis_stop=" << ToBoolString(is_axis_stop);
 }
@@ -299,6 +304,7 @@
 void WaylandEventSource::OnPointerFocusChanged(
     WaylandWindow* window,
     const gfx::PointF& location,
+    base::TimeTicks timestamp,
     wl::EventDispatchPolicy dispatch_policy) {
   bool focused = !!window;
   if (focused) {
@@ -317,8 +323,8 @@
   auto* target = window_manager_->GetCurrentPointerFocusedWindow();
   if (target) {
     EventType type = focused ? ET_MOUSE_ENTERED : ET_MOUSE_EXITED;
-    MouseEvent event(type, pointer_location_, pointer_location_,
-                     EventTimeForNow(), pointer_flags_, 0);
+    MouseEvent event(type, pointer_location_, pointer_location_, timestamp,
+                     pointer_flags_, 0);
     if (dispatch_policy == wl::EventDispatchPolicy::kImmediate) {
       SetTargetAndDispatchEvent(&event, target);
     } else {
@@ -335,14 +341,17 @@
 void WaylandEventSource::OnPointerButtonEvent(
     EventType type,
     int changed_button,
+    base::TimeTicks timestamp,
     WaylandWindow* window,
     wl::EventDispatchPolicy dispatch_policy) {
-  OnPointerButtonEvent(type, changed_button, window, dispatch_policy, false);
+  OnPointerButtonEvent(type, changed_button, timestamp, window, dispatch_policy,
+                       false);
 }
 
 void WaylandEventSource::OnPointerButtonEvent(
     EventType type,
     int changed_button,
+    base::TimeTicks timestamp,
     WaylandWindow* window,
     wl::EventDispatchPolicy dispatch_policy,
     bool allow_release_of_unpressed_button) {
@@ -375,8 +384,8 @@
   if (target) {
     // MouseEvent's flags should contain the button that was released too.
     int flags = pointer_flags_ | keyboard_modifiers_ | changed_button;
-    MouseEvent event(type, pointer_location_, pointer_location_,
-                     EventTimeForNow(), flags, changed_button);
+    MouseEvent event(type, pointer_location_, pointer_location_, timestamp,
+                     flags, changed_button);
     if (dispatch_policy == wl::EventDispatchPolicy::kImmediate) {
       SetTargetAndDispatchEvent(&event, target);
     } else {
@@ -401,12 +410,13 @@
 
 void WaylandEventSource::OnPointerMotionEvent(
     const gfx::PointF& location,
+    base::TimeTicks timestamp,
     wl::EventDispatchPolicy dispatch_policy) {
   pointer_location_ = location;
 
   int flags = pointer_flags_ | keyboard_modifiers_;
   MouseEvent event(ET_MOUSE_MOVED, pointer_location_, pointer_location_,
-                   EventTimeForNow(), flags, 0);
+                   timestamp, flags, 0);
   auto* target = window_manager_->GetCurrentPointerFocusedWindow();
 
   // A window may be deleted when the event arrived from the server.
@@ -421,9 +431,11 @@
   }
 }
 
-void WaylandEventSource::OnPointerAxisEvent(const gfx::Vector2dF& offset) {
-  EnsurePointerScrollData().dx += offset.x();
-  EnsurePointerScrollData().dy += offset.y();
+void WaylandEventSource::OnPointerAxisEvent(const gfx::Vector2dF& offset,
+                                            base::TimeTicks timestamp) {
+  EnsurePointerScrollData(timestamp);
+  pointer_scroll_data_->dx += offset.x();
+  pointer_scroll_data_->dy += offset.y();
 }
 
 void WaylandEventSource::OnResetPointerFlags() {
@@ -509,16 +521,19 @@
 }
 
 void WaylandEventSource::OnPointerAxisSourceEvent(uint32_t axis_source) {
-  EnsurePointerScrollData().axis_source = axis_source;
+  EnsurePointerScrollData(/*timestamp*/ absl::nullopt);
+  pointer_scroll_data_->axis_source = axis_source;
 }
 
-void WaylandEventSource::OnPointerAxisStopEvent(uint32_t axis) {
+void WaylandEventSource::OnPointerAxisStopEvent(uint32_t axis,
+                                                base::TimeTicks timestamp) {
+  EnsurePointerScrollData(timestamp);
   if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
-    EnsurePointerScrollData().dy = 0;
+    pointer_scroll_data_->dy = 0;
   } else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
-    EnsurePointerScrollData().dx = 0;
+    pointer_scroll_data_->dx = 0;
   }
-  EnsurePointerScrollData().is_axis_stop = true;
+  pointer_scroll_data_->is_axis_stop = true;
 }
 
 void WaylandEventSource::OnTouchPressEvent(
@@ -794,8 +809,8 @@
   pointer_scroll_data_set_.clear();
 
   ScrollEvent event(ET_SCROLL_FLING_CANCEL, pointer_location_,
-                    pointer_location_, EventTimeForNow(), pointer_flags_, 0, 0,
-                    0, 0, finger_count);
+                    pointer_location_, timestamp, pointer_flags_, 0, 0, 0, 0,
+                    finger_count);
 
   auto* target = window_manager_->GetCurrentPointerFocusedWindow();
 
@@ -814,12 +829,13 @@
     relative_pointer_location_.reset();
 }
 
-void WaylandEventSource::OnRelativePointerMotion(const gfx::Vector2dF& delta) {
+void WaylandEventSource::OnRelativePointerMotion(const gfx::Vector2dF& delta,
+                                                 base::TimeTicks timestamp) {
   DCHECK(relative_pointer_location_.has_value());
   // TODO(oshima): Investigate if we need to scale the delta
   // when surface_submission_in_pixel_coordinates is on.
   relative_pointer_location_ = *relative_pointer_location_ + delta;
-  OnPointerMotionEvent(*relative_pointer_location_,
+  OnPointerMotionEvent(*relative_pointer_location_, timestamp,
                        wl::EventDispatchPolicy::kImmediate);
 }
 
@@ -1020,12 +1036,13 @@
                         it->second->tilt.y());
 }
 
-WaylandEventSource::PointerScrollData&
-WaylandEventSource::EnsurePointerScrollData() {
+void WaylandEventSource::EnsurePointerScrollData(
+    const absl::optional<base::TimeTicks>& timestamp) {
   if (!pointer_scroll_data_)
     pointer_scroll_data_ = PointerScrollData();
-
-  return *pointer_scroll_data_;
+  if (!pointer_scroll_data_->timestamp && timestamp) {
+    pointer_scroll_data_->timestamp = *timestamp;
+  }
 }
 
 // This method behaves differently in Exo than in other window managers.
@@ -1037,6 +1054,15 @@
 // arrive.
 void WaylandEventSource::ProcessPointerScrollData() {
   DCHECK(pointer_scroll_data_);
+  // While it does not make sense for a server to send axis source only,
+  // the protocol does not explicitly specify it's illegal. Just skip if
+  // that happens.
+  if (!pointer_scroll_data_->timestamp) {
+    pointer_scroll_data_.reset();
+    return;
+  }
+  base::TimeTicks& timestamp = *pointer_scroll_data_->timestamp;
+
   int flags = pointer_flags_ | keyboard_modifiers_;
   // Dispatch Fling event if pointer.axis_stop is notified and the recent
   // pointer.axis events meets the criteria to start fling scroll.
@@ -1052,14 +1078,14 @@
     ScrollEvent event(pointer_scroll_data_->is_axis_stop
                           ? ET_SCROLL_FLING_START
                           : ET_SCROLL_FLING_CANCEL,
-                      pointer_location_, pointer_location_, EventTimeForNow(),
-                      flags, vx, vy, vx, vy, kGestureScrollFingerCount);
+                      pointer_location_, pointer_location_, timestamp, flags,
+                      vx, vy, vx, vy, kGestureScrollFingerCount);
 #else
     // In Linux there is no axis event with 0 delta when start scrolling.
     // A fling is therefore always started at this point.
     ScrollEvent event(ET_SCROLL_FLING_START, pointer_location_,
-                      pointer_location_, EventTimeForNow(), flags, vx, vy, vx,
-                      vy, kGestureScrollFingerCount);
+                      pointer_location_, timestamp, flags, vx, vy, vx, vy,
+                      kGestureScrollFingerCount);
     is_fling_active_ = true;
 #endif
     pointer_frames_.push_back(
@@ -1070,7 +1096,7 @@
             WL_POINTER_AXIS_SOURCE_WHEEL_TILT) {
       MouseWheelEvent event(
           gfx::Vector2d(pointer_scroll_data_->dx, pointer_scroll_data_->dy),
-          pointer_location_, pointer_location_, EventTimeForNow(), flags, 0);
+          pointer_location_, pointer_location_, timestamp, flags, 0);
       pointer_frames_.push_back(
           std::make_unique<FrameData>(event, base::NullCallback()));
     } else if (*pointer_scroll_data_->axis_source ==
@@ -1082,15 +1108,15 @@
       // From Wayland 1.23 this will be done through hold event.
       if (is_fling_active_) {
         is_fling_active_ = false;
-        ScrollEvent stop_fling_event(
-            ET_SCROLL_FLING_CANCEL, pointer_location_, pointer_location_,
-            EventTimeForNow(), flags, 0, 0, 0, 0, kGestureScrollFingerCount);
+        ScrollEvent stop_fling_event(ET_SCROLL_FLING_CANCEL, pointer_location_,
+                                     pointer_location_, timestamp, flags, 0, 0,
+                                     0, 0, kGestureScrollFingerCount);
         pointer_frames_.push_back(std::make_unique<FrameData>(
             stop_fling_event, base::NullCallback()));
       }
 #endif
       ScrollEvent event(ET_SCROLL, pointer_location_, pointer_location_,
-                        EventTimeForNow(), flags, pointer_scroll_data_->dx,
+                        timestamp, flags, pointer_scroll_data_->dx,
                         pointer_scroll_data_->dy, pointer_scroll_data_->dx,
                         pointer_scroll_data_->dy, kGestureScrollFingerCount);
       pointer_frames_.push_back(
diff --git a/ui/ozone/platform/wayland/host/wayland_event_source.h b/ui/ozone/platform/wayland/host/wayland_event_source.h
index e9cc5bc..0d6d342 100644
--- a/ui/ozone/platform/wayland/host/wayland_event_source.h
+++ b/ui/ozone/platform/wayland/host/wayland_event_source.h
@@ -110,22 +110,28 @@
   // WaylandPointer::Delegate
   void OnPointerFocusChanged(WaylandWindow* window,
                              const gfx::PointF& location,
+                             base::TimeTicks timestamp,
                              wl::EventDispatchPolicy dispatch_policy) override;
   void OnPointerButtonEvent(EventType evtype,
                             int changed_button,
+                            base::TimeTicks timestamp,
                             WaylandWindow* window,
                             wl::EventDispatchPolicy dispatch_policy) override;
   void OnPointerButtonEvent(EventType evtype,
                             int changed_button,
+                            base::TimeTicks timestamp,
                             WaylandWindow* window,
                             wl::EventDispatchPolicy dispatch_policy,
                             bool allow_release_of_unpressed_button) override;
   void OnPointerMotionEvent(const gfx::PointF& location,
+                            base::TimeTicks timestamp,
                             wl::EventDispatchPolicy dispatch_policy) override;
-  void OnPointerAxisEvent(const gfx::Vector2dF& offset) override;
+  void OnPointerAxisEvent(const gfx::Vector2dF& offset,
+                          base::TimeTicks timestamp) override;
   void OnPointerFrameEvent() override;
   void OnPointerAxisSourceEvent(uint32_t axis_source) override;
-  void OnPointerAxisStopEvent(uint32_t axis) override;
+  void OnPointerAxisStopEvent(uint32_t axis,
+                              base::TimeTicks timestamp) override;
   void OnResetPointerFlags() override;
   const gfx::PointF& GetPointerLocation() const override;
   bool IsPointerButtonPressed(EventFlags button) const override;
@@ -172,7 +178,8 @@
 
   // WaylandZwpRelativePointerManager::Delegate:
   void SetRelativePointerMotionEnabled(bool enabled) override;
-  void OnRelativePointerMotion(const gfx::Vector2dF& delta) override;
+  void OnRelativePointerMotion(const gfx::Vector2dF& delta,
+                               base::TimeTicks timestamp) override;
 
  private:
   struct PointerScrollData {
@@ -189,6 +196,7 @@
     float dy = 0.0f;
     base::TimeDelta dt;
     bool is_axis_stop = false;
+    absl::optional<base::TimeTicks> timestamp;
 
     void DumpState(std::ostream& out) const;
   };
@@ -233,7 +241,8 @@
   void OnTouchReleaseInternal(PointerId id);
 
   // Ensure a valid instance of the PointerScrollData class member.
-  PointerScrollData& EnsurePointerScrollData();
+  void EnsurePointerScrollData(
+      const absl::optional<base::TimeTicks>& timestamp);
 
   void ProcessPointerScrollData();
 
diff --git a/ui/ozone/platform/wayland/host/wayland_pointer.cc b/ui/ozone/platform/wayland/host/wayland_pointer.cc
index db24bae5..4e3b24f 100644
--- a/ui/ozone/platform/wayland/host/wayland_pointer.cc
+++ b/ui/ozone/platform/wayland/host/wayland_pointer.cc
@@ -9,6 +9,7 @@
 
 #include "base/logging.h"
 #include "base/version.h"
+#include "ui/events/base_event_utils.h"
 #include "ui/events/event.h"
 #include "ui/events/types/event_type.h"
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
@@ -60,7 +61,7 @@
   // Even though, WaylandPointer::Leave is always called when Wayland destroys
   // wl_pointer, it's better to be explicit as some Wayland compositors may have
   // bugs.
-  delegate_->OnPointerFocusChanged(nullptr, {},
+  delegate_->OnPointerFocusChanged(nullptr, {}, EventTimeForNow(),
                                    wl::EventDispatchPolicy::kImmediate);
   delegate_->OnResetPointerFlags();
 }
@@ -72,6 +73,8 @@
                              wl_surface* surface,
                              wl_fixed_t surface_x,
                              wl_fixed_t surface_y) {
+  // enter event doesn't have timestamp. Use EventTimeForNow().
+  const auto timestamp = EventTimeForNow();
   auto* self = static_cast<WaylandPointer*>(data);
 
   if (self->connection_->IsDragInProgress()) {
@@ -92,7 +95,7 @@
 
   self->delegate_->OnPointerFocusChanged(
       window, self->connection_->MaybeConvertLocation(location, window),
-      EventDispatchPolicyForPlatform());
+      timestamp, EventDispatchPolicyForPlatform());
 }
 
 // static
@@ -100,6 +103,8 @@
                              wl_pointer* pointer,
                              uint32_t serial,
                              wl_surface* surface) {
+  // leave event doesn't have timestamp. Use EventTimeForNow().
+  const auto timestamp = EventTimeForNow();
   auto* self = static_cast<WaylandPointer*>(data);
 
   if (self->connection_->IsDragInProgress()) {
@@ -111,8 +116,9 @@
 
   auto event_dispatch_policy = EventDispatchPolicyForPlatform();
 
-  self->delegate_->OnPointerFocusChanged(
-      nullptr, self->delegate_->GetPointerLocation(), event_dispatch_policy);
+  self->delegate_->OnPointerFocusChanged(nullptr,
+                                         self->delegate_->GetPointerLocation(),
+                                         timestamp, event_dispatch_policy);
 }
 
 // static
@@ -134,7 +140,7 @@
 
   self->delegate_->OnPointerMotionEvent(
       self->connection_->MaybeConvertLocation(location, target),
-      EventDispatchPolicyForPlatform());
+      wl::EventMillisecondsToTimeTicks(time), EventDispatchPolicyForPlatform());
 }
 
 // static
@@ -174,9 +180,9 @@
     self->connection_->serial_tracker().UpdateSerial(
         wl::SerialType::kMousePress, serial);
   }
-  self->delegate_->OnPointerButtonEvent(type, changed_button,
-                                        /*window=*/nullptr,
-                                        EventDispatchPolicyForPlatform());
+  self->delegate_->OnPointerButtonEvent(
+      type, changed_button, wl::EventMillisecondsToTimeTicks(time),
+      /*window=*/nullptr, EventDispatchPolicyForPlatform());
 }
 
 // static
@@ -205,10 +211,11 @@
   // If we did not receive the axis event source explicitly, set it to the mouse
   // wheel so far.  Should this be a part of some complex event coming from the
   // different source, the compositor will let us know sooner or later.
+  auto timestamp = wl::EventMillisecondsToTimeTicks(time);
   if (!self->axis_source_received_) {
     self->delegate_->OnPointerAxisSourceEvent(WL_POINTER_AXIS_SOURCE_WHEEL);
   }
-  self->delegate_->OnPointerAxisEvent(offset);
+  self->delegate_->OnPointerAxisEvent(offset, timestamp);
 }
 
 // ---- Version 5 ----
@@ -237,7 +244,8 @@
                                 uint32_t time,
                                 uint32_t axis) {
   auto* self = static_cast<WaylandPointer*>(data);
-  self->delegate_->OnPointerAxisStopEvent(axis);
+  self->delegate_->OnPointerAxisStopEvent(
+      axis, wl::EventMillisecondsToTimeTicks(time));
 }
 
 // static
diff --git a/ui/ozone/platform/wayland/host/wayland_pointer.h b/ui/ozone/platform/wayland/host/wayland_pointer.h
index 1570742d..968b1e0 100644
--- a/ui/ozone/platform/wayland/host/wayland_pointer.h
+++ b/ui/ozone/platform/wayland/host/wayland_pointer.h
@@ -12,6 +12,10 @@
 #include "ui/events/types/event_type.h"
 #include "ui/ozone/platform/wayland/common/wayland_object.h"
 
+namespace base {
+class TimeTicks;
+}
+
 namespace gfx {
 class PointF;
 class Vector2dF;
@@ -122,24 +126,30 @@
   virtual void OnPointerFocusChanged(
       WaylandWindow* window,
       const gfx::PointF& location,
+      base::TimeTicks timestamp,
       wl::EventDispatchPolicy dispatch_policy) = 0;
   virtual void OnPointerButtonEvent(
       EventType evtype,
       int changed_button,
+      base::TimeTicks timestamp,
       WaylandWindow* window,
       wl::EventDispatchPolicy dispatch_policy) = 0;
   virtual void OnPointerButtonEvent(EventType evtype,
                                     int changed_button,
+                                    base::TimeTicks timestamp,
                                     WaylandWindow* window,
                                     wl::EventDispatchPolicy dispatch_policy,
                                     bool allow_release_of_unpressed_button) = 0;
   virtual void OnPointerMotionEvent(
       const gfx::PointF& location,
+      base::TimeTicks timestamp,
       wl::EventDispatchPolicy dispatch_policy) = 0;
-  virtual void OnPointerAxisEvent(const gfx::Vector2dF& offset) = 0;
+  virtual void OnPointerAxisEvent(const gfx::Vector2dF& offset,
+                                  base::TimeTicks timestamp) = 0;
   virtual void OnPointerFrameEvent() = 0;
   virtual void OnPointerAxisSourceEvent(uint32_t axis_source) = 0;
-  virtual void OnPointerAxisStopEvent(uint32_t axis) = 0;
+  virtual void OnPointerAxisStopEvent(uint32_t axis,
+                                      base::TimeTicks timestamp) = 0;
   virtual void OnResetPointerFlags() = 0;
   virtual const gfx::PointF& GetPointerLocation() const = 0;
   virtual bool IsPointerButtonPressed(EventFlags button) const = 0;
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
index 38d26fc..8f262de 100644
--- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
@@ -25,6 +25,7 @@
 #include "ui/base/ui_base_features.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
+#include "ui/events/base_event_utils.h"
 #include "ui/events/event.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/platform/platform_event_source.h"
@@ -181,7 +182,7 @@
   }
 
   auto state = state_;
-  HandleDropAndResetState();
+  HandleDropAndResetState(EventTimeForNow());
 
   return state != State::kCancelled;
 }
@@ -222,6 +223,7 @@
 
 void WaylandWindowDragController::OnDragEnter(WaylandWindow* window,
                                               const gfx::PointF& location,
+                                              base::TimeTicks timestamp,
                                               uint32_t serial) {
   // Drag-and-drop sessions may be terminated by the client while drag-and-drop
   // server events are still in-flight. No-op if this is the case.
@@ -245,7 +247,7 @@
   // Check if this is necessary.
   if (*drag_source_ == DragEventSource::kMouse) {
     pointer_delegate_->OnPointerFocusChanged(
-        window, location, wl::EventDispatchPolicy::kImmediate);
+        window, location, timestamp, wl::EventDispatchPolicy::kImmediate);
   } else {
     touch_delegate_->OnTouchFocusChanged(window);
   }
@@ -265,7 +267,8 @@
   data_offer_->Accept(serial, kMimeTypeChromiumWindow);
 }
 
-void WaylandWindowDragController::OnDragMotion(const gfx::PointF& location) {
+void WaylandWindowDragController::OnDragMotion(const gfx::PointF& location,
+                                               base::TimeTicks timestamp) {
   // Drag-and-drop sessions may be terminated by the client while drag-and-drop
   // server events are still in-flight. No-op if this is the case.
   if (!IsActiveDragAndDropSession()) {
@@ -293,21 +296,21 @@
 
   if (*drag_source_ == DragEventSource::kMouse) {
     pointer_delegate_->OnPointerMotionEvent(
-        location, wl::EventDispatchPolicy::kImmediate);
+        location, timestamp, wl::EventDispatchPolicy::kImmediate);
   } else {
     const auto touch_pointer_ids = touch_delegate_->GetActiveTouchPointIds();
     LOG_IF(WARNING, touch_pointer_ids.size() != 1u)
         << "Unexpected touch drag motion. Active touch_points: "
         << touch_pointer_ids.size();
     if (!touch_pointer_ids.empty()) {
-      touch_delegate_->OnTouchMotionEvent(location, base::TimeTicks::Now(),
+      touch_delegate_->OnTouchMotionEvent(location, timestamp,
                                           touch_pointer_ids[0],
                                           wl::EventDispatchPolicy::kImmediate);
     }
   }
 }
 
-void WaylandWindowDragController::OnDragLeave() {
+void WaylandWindowDragController::OnDragLeave(base::TimeTicks timestamp) {
   // Drag and drop sessions may be terminated by the client while drag-and-drop
   // server events may still be in-flight. No-op if this is the case.
   if (!IsActiveDragAndDropSession()) {
@@ -354,7 +357,8 @@
 
   if (*drag_source_ == DragEventSource::kMouse) {
     pointer_delegate_->OnPointerMotionEvent(
-        {pointer_location_.x(), -1}, wl::EventDispatchPolicy::kImmediate);
+        {pointer_location_.x(), -1}, timestamp,
+        wl::EventDispatchPolicy::kImmediate);
   } else {
     const auto touch_pointer_ids = touch_delegate_->GetActiveTouchPointIds();
     if (!touch_pointer_ids.empty()) {
@@ -364,14 +368,13 @@
       // to work around the threshold in ScrollSnapController otherwise,
       // the drag event is discarded.
       touch_delegate_->OnTouchMotionEvent(
-          {pointer_location_.x(), kHorizontalRailExitThreshold},
-          base::TimeTicks::Now(), touch_pointer_ids[0],
-          wl::EventDispatchPolicy::kImmediate);
+          {pointer_location_.x(), kHorizontalRailExitThreshold}, timestamp,
+          touch_pointer_ids[0], wl::EventDispatchPolicy::kImmediate);
     }
   }
 }
 
-void WaylandWindowDragController::OnDragDrop() {
+void WaylandWindowDragController::OnDragDrop(base::TimeTicks timestamp) {
   // Drag-and-drop sessions may be terminated by the client while drag-and-drop
   // server events are still in-flight. No-op if this is the case.
   if (!IsActiveDragAndDropSession()) {
@@ -397,6 +400,7 @@
 // when drop happens, since it is the only event sent by the server regardless
 // where it happens, inside or outside toplevel surfaces.
 void WaylandWindowDragController::OnDataSourceFinish(WaylandDataSource* source,
+                                                     base::TimeTicks timestamp,
                                                      bool completed) {
   CHECK_GE(state_, State::kAttached);
   CHECK_EQ(data_source_.get(), source);
@@ -421,7 +425,7 @@
       // TODO: check if this usage is correct.
 
       pointer_delegate_->OnPointerFocusChanged(
-          dragged_window_, pointer_location_,
+          dragged_window_, pointer_location_, timestamp,
           wl::EventDispatchPolicy::kImmediate);
     } else {
       touch_delegate_->OnTouchFocusChanged(dragged_window_);
@@ -439,7 +443,7 @@
     VLOG(1) << "Quiting Loop : Detached";
     QuitLoop();
   } else {
-    HandleDropAndResetState();
+    HandleDropAndResetState(timestamp);
   }
 
   data_device_->ResetDragDelegate();
@@ -526,7 +530,8 @@
 
   if (should_cancel_drag) {
     LOG(ERROR) << "OnDataSourceFinish";
-    OnDataSourceFinish(data_source_.get(), /*completed=*/false);
+    OnDataSourceFinish(data_source_.get(), EventTimeForNow(),
+                       /*completed=*/false);
   }
 }
 
@@ -553,7 +558,8 @@
 // Dispatch mouse release event (to tell clients that the drop just happened)
 // clear focus and reset internal state. Must be called when the session is
 // about to finish.
-void WaylandWindowDragController::HandleDropAndResetState() {
+void WaylandWindowDragController::HandleDropAndResetState(
+    base::TimeTicks timestamp) {
   DCHECK(state_ == State::kDropped || state_ == State::kCancelled);
   VLOG(1) << "Notifying drop. window=" << pointer_grab_owner_;
 
@@ -569,14 +575,13 @@
   if (*drag_source_ == DragEventSource::kMouse) {
     if (pointer_grab_owner_) {
       pointer_delegate_->OnPointerButtonEvent(
-          ET_MOUSE_RELEASED, EF_LEFT_MOUSE_BUTTON, pointer_grab_owner_,
-          wl::EventDispatchPolicy::kImmediate);
+          ET_MOUSE_RELEASED, EF_LEFT_MOUSE_BUTTON, timestamp,
+          pointer_grab_owner_, wl::EventDispatchPolicy::kImmediate);
     }
   } else {
     const auto touch_pointer_ids = touch_delegate_->GetActiveTouchPointIds();
     if (!touch_pointer_ids.empty()) {
-      touch_delegate_->OnTouchReleaseEvent(base::TimeTicks::Now(),
-                                           touch_pointer_ids[0],
+      touch_delegate_->OnTouchReleaseEvent(timestamp, touch_pointer_ids[0],
                                            wl::EventDispatchPolicy::kImmediate);
     }
   }
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.h b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.h
index 15c8e24a..9c8f76d 100644
--- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.h
+++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.h
@@ -131,14 +131,18 @@
   void OnDragOffer(std::unique_ptr<WaylandDataOffer> offer) override;
   void OnDragEnter(WaylandWindow* window,
                    const gfx::PointF& location,
+                   base::TimeTicks timestamp,
                    uint32_t serial) override;
-  void OnDragMotion(const gfx::PointF& location) override;
-  void OnDragLeave() override;
-  void OnDragDrop() override;
+  void OnDragMotion(const gfx::PointF& location,
+                    base::TimeTicks timestamp) override;
+  void OnDragLeave(base::TimeTicks timestamp) override;
+  void OnDragDrop(base::TimeTicks timestamp) override;
   const WaylandWindow* GetDragTarget() const override;
 
   // WaylandDataSource::Delegate
-  void OnDataSourceFinish(WaylandDataSource* source, bool completed) override;
+  void OnDataSourceFinish(WaylandDataSource* source,
+                          base::TimeTicks timestamp,
+                          bool completed) override;
   void OnDataSourceSend(WaylandDataSource* source,
                         const std::string& mime_type,
                         std::string* contents) override;
@@ -155,7 +159,7 @@
   void HandleMotionEvent(LocatedEvent* event);
   // Handles the mouse button release (i.e: drop). Dispatches the required
   // events and resets the internal state.
-  void HandleDropAndResetState();
+  void HandleDropAndResetState(base::TimeTicks timestamp);
   // Registers as the top level PlatformEvent dispatcher and runs a nested
   // RunLoop, which blocks until the DnD session finishes.
   void RunLoop();
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
index 963ad652..1d4a1daf 100644
--- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
@@ -1523,7 +1523,7 @@
   // drop handling code at window drag controller does not call into the above
   // destroyed dragged window.
   EXPECT_CALL(delegate_, DispatchEvent(_)).Times(0);
-  drag_controller()->OnDragDrop();
+  drag_controller()->OnDragDrop(EventTimeForNow());
 
   // 6. Verifies that related state is correctly reset after drop.
   EXPECT_EQ(State::kIdle, drag_controller()->state());
@@ -1583,7 +1583,7 @@
     EXPECT_CALL(delegate_2, DispatchEvent(_)).Times(0);
     EXPECT_CALL(delegate_2, OnBoundsChanged(_)).Times(0);
     SendDndMotionForWindowDrag({12, 10});
-    drag_controller()->OnDragDrop();
+    drag_controller()->OnDragDrop(EventTimeForNow());
     Mock::VerifyAndClearExpectations(&delegate_2);
 
     // Verify that internal "last cursor position" is not updated after the
@@ -1808,7 +1808,7 @@
     EXPECT_CALL(delegate_2, DispatchEvent(_)).Times(0);
     EXPECT_CALL(delegate_2, OnBoundsChanged(_)).Times(0);
     SendDndMotionForWindowDrag({12, 10});
-    drag_controller()->OnDragDrop();
+    drag_controller()->OnDragDrop(EventTimeForNow());
 
     // Verify that internal "last cursor position" is not updated after the
     // grab owner is destroyed.
@@ -1867,7 +1867,7 @@
   // ended.
   EXPECT_CALL(delegate_, DispatchEvent(_)).Times(0);
   SendDndMotionForWindowDrag({13, 10});
-  drag_controller()->OnDragDrop();
+  drag_controller()->OnDragDrop(EventTimeForNow());
 
   // Verifies that related state is correctly reset.
   EXPECT_EQ(State::kIdle, drag_controller()->state());
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc b/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc
index 9cc8ae8..833da50 100644
--- a/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc
+++ b/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc
@@ -9,6 +9,7 @@
 #include "base/logging.h"
 #include "build/chromeos_buildflags.h"
 #include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/ozone/platform/wayland/common/wayland_util.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
 #include "ui/ozone/platform/wayland/host/wayland_cursor_position.h"
 #include "ui/ozone/platform/wayland/host/wayland_event_source.h"
@@ -101,13 +102,11 @@
     uint32_t fingers) {
   auto* self = static_cast<WaylandZwpPointerGestures*>(data);
 
-  base::TimeTicks timestamp = base::TimeTicks() + base::Milliseconds(time);
-
   self->current_scale_ = 1;
 
-  self->delegate_->OnPinchEvent(ET_GESTURE_PINCH_BEGIN,
-                                gfx::Vector2dF() /*delta*/, timestamp,
-                                self->obj_.id());
+  self->delegate_->OnPinchEvent(
+      ET_GESTURE_PINCH_BEGIN, gfx::Vector2dF() /*delta*/,
+      wl::EventMillisecondsToTimeTicks(time), self->obj_.id());
 }
 
 // static
@@ -138,11 +137,10 @@
   const auto scale_delta = wl_fixed_to_double(scale);
 #endif
 
-  base::TimeTicks timestamp = base::TimeTicks() + base::Milliseconds(time);
-
   gfx::Vector2dF delta = {static_cast<float>(wl_fixed_to_double(dx)),
                           static_cast<float>(wl_fixed_to_double(dy))};
-  self->delegate_->OnPinchEvent(ET_GESTURE_PINCH_UPDATE, delta, timestamp,
+  self->delegate_->OnPinchEvent(ET_GESTURE_PINCH_UPDATE, delta,
+                                wl::EventMillisecondsToTimeTicks(time),
                                 self->obj_.id(), scale_delta);
 }
 
@@ -154,11 +152,9 @@
     int32_t cancelled) {
   auto* self = static_cast<WaylandZwpPointerGestures*>(data);
 
-  base::TimeTicks timestamp = base::TimeTicks() + base::Milliseconds(time);
-
-  self->delegate_->OnPinchEvent(ET_GESTURE_PINCH_END,
-                                gfx::Vector2dF() /*delta*/, timestamp,
-                                self->obj_.id());
+  self->delegate_->OnPinchEvent(
+      ET_GESTURE_PINCH_END, gfx::Vector2dF() /*delta*/,
+      wl::EventMillisecondsToTimeTicks(time), self->obj_.id());
 }
 
 #if defined(ZWP_POINTER_GESTURE_HOLD_V1_BEGIN_SINCE_VERSION)
@@ -172,11 +168,9 @@
     uint32_t fingers) {
   auto* self = static_cast<WaylandZwpPointerGestures*>(data);
 
-  base::TimeTicks timestamp = base::TimeTicks() + base::Milliseconds(time);
-
-  self->delegate_->OnHoldEvent(ET_TOUCH_PRESSED, fingers, timestamp,
-                               self->obj_.id(),
-                               wl::EventDispatchPolicy::kImmediate);
+  self->delegate_->OnHoldEvent(
+      ET_TOUCH_PRESSED, fingers, wl::EventMillisecondsToTimeTicks(time),
+      self->obj_.id(), wl::EventDispatchPolicy::kImmediate);
 }
 #endif
 
@@ -190,11 +184,10 @@
     int32_t cancelled) {
   auto* self = static_cast<WaylandZwpPointerGestures*>(data);
 
-  base::TimeTicks timestamp = base::TimeTicks() + base::Milliseconds(time);
-
   self->delegate_->OnHoldEvent(
-      cancelled ? ET_TOUCH_CANCELLED : ET_TOUCH_RELEASED, 0, timestamp,
-      self->obj_.id(), wl::EventDispatchPolicy::kImmediate);
+      cancelled ? ET_TOUCH_CANCELLED : ET_TOUCH_RELEASED, 0,
+      wl::EventMillisecondsToTimeTicks(time), self->obj_.id(),
+      wl::EventDispatchPolicy::kImmediate);
 }
 #endif
 
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.cc b/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.cc
index a5c05954..9197cb3 100644
--- a/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.cc
+++ b/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.cc
@@ -7,6 +7,7 @@
 #include <relative-pointer-unstable-v1-client-protocol.h>
 
 #include "base/logging.h"
+#include "build/buildflag.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
 #include "ui/ozone/platform/wayland/host/wayland_event_source.h"
 #include "ui/ozone/platform/wayland/host/wayland_pointer.h"
@@ -96,7 +97,14 @@
       static_cast<float>(wl_fixed_to_double(dx_unaccel)),
       static_cast<float>(wl_fixed_to_double(dy_unaccel))};
 
-  self->delegate_->OnRelativePointerMotion(delta);
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  // The unit of timestamp should be same as unit used in event events, which is
+  // one uint32_t (it is CPU clock time in milliseconds). ChromeOS is using only
+  // using utime_lo, and utime_hi should always be zero.
+  CHECK(!utime_hi);
+#endif
+  self->delegate_->OnRelativePointerMotion(
+      delta, wl::EventMillisecondsToTimeTicks(utime_lo));
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.h b/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.h
index 6b56ebc..8c96ad9 100644
--- a/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.h
+++ b/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.h
@@ -8,6 +8,10 @@
 #include "base/memory/raw_ptr.h"
 #include "ui/ozone/platform/wayland/common/wayland_object.h"
 
+namespace base {
+class TimeTicks;
+}
+
 namespace gfx {
 class Vector2dF;
 }  // namespace gfx
@@ -63,7 +67,8 @@
 class WaylandZwpRelativePointerManager::Delegate {
  public:
   virtual void SetRelativePointerMotionEnabled(bool enabled) = 0;
-  virtual void OnRelativePointerMotion(const gfx::Vector2dF& delta) = 0;
+  virtual void OnRelativePointerMotion(const gfx::Vector2dF& delta,
+                                       base::TimeTicks timestamp) = 0;
 };
 
 }  // namespace ui
diff --git a/ui/qt/BUILD.gn b/ui/qt/BUILD.gn
index 79c92759..2da7845e 100644
--- a/ui/qt/BUILD.gn
+++ b/ui/qt/BUILD.gn
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/linux/pkg_config.gni")
 import("//build/config/sysroot.gni")
 import("//printing/buildflags/buildflags.gni")
diff --git a/ui/qt/qt.gni b/ui/qt/qt.gni
index 03611e3..5fa4253a 100644
--- a/ui/qt/qt.gni
+++ b/ui/qt/qt.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 import("//build/config/sysroot.gni")
 
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 442f6d2..e1bc7d4e4 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -83,6 +83,7 @@
     "accessibility/views_ax_tree_manager.h",
     "accessibility/widget_ax_tree_id_map.h",
     "accessible_pane_view.h",
+    "action_view_controller.h",
     "animation/animation_abort_handle.h",
     "animation/animation_builder.h",
     "animation/animation_delegate_views.h",
@@ -544,6 +545,7 @@
     "//skia",
     "//third_party/icu",
     "//ui/accessibility",
+    "//ui/actions",
     "//ui/base/clipboard",
     "//ui/base/dragdrop/mojom",
     "//ui/base/emoji",
@@ -1202,6 +1204,7 @@
   sources = [
     "accessibility/accessibility_paint_checks_unittest.cc",
     "accessible_pane_view_unittest.cc",
+    "action_view_controller_unittest.cc",
     "animation/animation_builder_unittest.cc",
     "animation/bounds_animator_unittest.cc",
     "animation/bubble_slide_animator_unittest.cc",
@@ -1338,6 +1341,7 @@
     "//testing/gtest",
     "//third_party/icu",
     "//ui/accessibility",
+    "//ui/actions",
     "//ui/base",
     "//ui/base:test_support",
     "//ui/base/clipboard",
diff --git a/ui/views/action_view_controller.h b/ui/views/action_view_controller.h
new file mode 100644
index 0000000..770ce5c
--- /dev/null
+++ b/ui/views/action_view_controller.h
@@ -0,0 +1,132 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ACTION_VIEW_CONTROLLER_H_
+#define UI_VIEWS_ACTION_VIEW_CONTROLLER_H_
+
+#include "base/callback_list.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/actions/actions.h"
+#include "ui/views/view_tracker.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+class View;
+
+class VIEWS_EXPORT ActionController {
+ public:
+  ActionController() = default;
+  ActionController(const ActionController&) = delete;
+  ActionController& operator=(const ActionController&) = delete;
+  virtual ~ActionController() = default;
+  void ActionItemChanged() {}
+  void ActionItemChangedInterim(View* view, actions::ActionItem* action_item) {}
+  void SetActionView(View* action_view) {}
+  void SetActionItem(base::WeakPtr<actions::ActionItem> action_item) {}
+};
+
+template <typename ViewT>
+struct VIEWS_EXPORT ActionViewControllerSuperClassT {
+  using SuperClass = ActionController;
+};
+
+template <typename ViewT,
+          typename SuperClassViewControllerT =
+              typename ActionViewControllerSuperClassT<ViewT>::SuperClass>
+class VIEWS_EXPORT ActionViewController : public SuperClassViewControllerT {
+ public:
+  ActionViewController() = default;
+  ActionViewController(ViewT* view,
+                       base::WeakPtr<actions::ActionItem> action_item) {
+    SetActionView(view);
+    SetActionItem(action_item);
+  }
+  explicit ActionViewController(ViewT* view) { SetActionView(view); }
+  ActionViewController(const ActionViewController&) = delete;
+  ActionViewController& operator=(const ActionViewController&) = delete;
+  ~ActionViewController() override = default;
+
+  void ActionItemChanged() {
+    ViewT* action_view = GetActionView();
+    actions::ActionItem* action_item = GetActionItem();
+    if (!action_view || !action_item) {
+      return;
+    }
+    ActionItemChangedInterim(action_view, action_item);
+  }
+
+  void ActionItemChangedInterim(ViewT* view, actions::ActionItem* action_item) {
+    SuperClassViewControllerT::ActionItemChangedInterim(view, action_item);
+    ActionItemChangedImpl(view, action_item);
+  }
+
+  void SetActionItem(base::WeakPtr<actions::ActionItem> action_item) {
+    if (GetActionItem() == action_item.get()) {
+      return;
+    }
+    action_item_ = action_item;
+    action_changed_subscription_ = {};
+    LinkActionItemAndView();
+    // Calling this method up to the super classes allows the action item to be
+    // accessible at each super class level of the template.
+    SuperClassViewControllerT::SetActionItem(action_item);
+  }
+
+  void LinkActionItemAndView() {
+    ViewT* action_view = GetActionView();
+    actions::ActionItem* action_item = GetActionItem();
+    if (!action_item || !action_view) {
+      return;
+    }
+    action_changed_subscription_ =
+        action_item->AddActionChangedCallback(base::BindRepeating(
+            &ActionViewController<ViewT,
+                                  SuperClassViewControllerT>::ActionItemChanged,
+            base::Unretained(this)));
+    ActionItemChanged();
+    action_view->InvalidateLayout();
+    action_view->SchedulePaint();
+  }
+
+  void TriggerAction() {
+    actions::ActionItem* action_item = GetActionItem();
+    if (action_item) {
+      action_item->InvokeAction();
+    }
+  }
+
+  ViewT* GetActionView() {
+    return static_cast<ViewT*>(action_view_tracker_.view());
+  }
+
+  void SetActionView(ViewT* action_view) {
+    if (GetActionView() == action_view) {
+      return;
+    }
+    action_view_tracker_.SetView(action_view);
+    // Calling this method up to the super classes allows the view to be
+    // accessible at each super class level of the template as well as get the
+    // specific behaviors set on the view of the super classes.
+    SuperClassViewControllerT::SetActionView(action_view);
+    SetActionViewImpl(action_view);
+    LinkActionItemAndView();
+  }
+
+  actions::ActionItem* GetActionItemForTesting() { return GetActionItem(); }
+
+ private:
+  actions::ActionItem* GetActionItem() { return action_item_.get(); }
+  void SetActionViewImpl(ViewT* action_view) {}
+  void ActionItemChangedImpl(ViewT* action_view,
+                             actions::ActionItem* action_item);
+
+  views::ViewTracker action_view_tracker_;
+  base::WeakPtr<actions::ActionItem> action_item_ = nullptr;
+  base::CallbackListSubscription action_changed_subscription_;
+};
+
+}  // namespace views
+
+#endif  // UI_VIEWS_ACTION_VIEW_CONTROLLER_H_
diff --git a/ui/views/action_view_controller_unittest.cc b/ui/views/action_view_controller_unittest.cc
new file mode 100644
index 0000000..b42dc1d
--- /dev/null
+++ b/ui/views/action_view_controller_unittest.cc
@@ -0,0 +1,142 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/action_view_controller.h"
+
+#include <memory>
+#include <utility>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/actions/actions.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/event.h"
+#include "ui/views/controls/button/md_text_button.h"
+#include "ui/views/test/button_test_api.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/view.h"
+
+namespace {
+const std::u16string kActionTextDisabled = u"Test Action Disabled";
+const std::u16string kActionTextEnabled = u"Test Action Enabled";
+constexpr int kTestActionIdDisabled = 0;
+constexpr int kTestActionIdEnabled = 1;
+
+std::unique_ptr<actions::ActionItem> CreateDisabledActionItem() {
+  return actions::ActionItem::Builder()
+      .SetText(kActionTextDisabled)
+      .SetActionId(kTestActionIdDisabled)
+      .SetVisible(true)
+      .SetEnabled(false)
+      .Build();
+}
+
+std::unique_ptr<actions::ActionItem> CreateEnabledActionItem() {
+  return actions::ActionItem::Builder()
+      .SetText(kActionTextEnabled)
+      .SetActionId(kTestActionIdEnabled)
+      .SetVisible(true)
+      .SetEnabled(true)
+      .Build();
+}
+
+}  // namespace
+
+namespace views {
+
+using ActionViewControllerTest = ViewsTestBase;
+
+// Test changing the action item will trigger the action changed callback on
+// both the derived and base class controller.
+TEST_F(ActionViewControllerTest, TestActionChangedCallbackCalled) {
+  std::unique_ptr<actions::ActionItem> action_item = CreateDisabledActionItem();
+  auto action_view = std::make_unique<MdTextButton>();
+  EXPECT_EQ(action_view->GetText(), u"");
+  EXPECT_TRUE(action_view->GetEnabled());
+  auto action_view_controller =
+      std::make_unique<ActionViewController<MdTextButton>>(
+          action_view.get(), action_item->GetAsWeakPtr());
+  EXPECT_EQ(action_view->GetText(), kActionTextDisabled);
+  EXPECT_FALSE(action_view->GetEnabled());
+  action_item->SetText(kActionTextEnabled);
+  action_item->SetEnabled(true);
+  EXPECT_EQ(action_view->GetText(), kActionTextEnabled);
+  EXPECT_TRUE(action_view->GetEnabled());
+}
+
+// Test reassigning to variable of base class type still has access to action
+// item and action views
+TEST_F(ActionViewControllerTest, TestReasignToBaseClass) {
+  std::unique_ptr<actions::ActionItem> action_item = CreateDisabledActionItem();
+  auto action_view = std::make_unique<MdTextButton>();
+  auto action_view_controller =
+      std::make_unique<ActionViewController<MdTextButton>>(
+          action_view.get(), action_item->GetAsWeakPtr());
+  std::unique_ptr<ActionViewController<View>> base_action_view_controller =
+      std::move(action_view_controller);
+  EXPECT_NE(base_action_view_controller->GetActionView(), nullptr);
+  EXPECT_NE(base_action_view_controller->GetActionItemForTesting(), nullptr);
+}
+
+// Test reassigning action item.
+TEST_F(ActionViewControllerTest, TestReassignActionItem) {
+  std::unique_ptr<actions::ActionItem> disabled_action_item =
+      CreateDisabledActionItem();
+  auto action_view = std::make_unique<MdTextButton>();
+  auto action_view_controller =
+      std::make_unique<ActionViewController<MdTextButton>>(
+          action_view.get(), disabled_action_item->GetAsWeakPtr());
+  EXPECT_EQ(action_view->GetText(), kActionTextDisabled);
+  EXPECT_FALSE(action_view->GetEnabled());
+  std::unique_ptr<actions::ActionItem> enabled_action_item =
+      CreateEnabledActionItem();
+  action_view_controller->SetActionItem(enabled_action_item->GetAsWeakPtr());
+  EXPECT_EQ(action_view->GetText(), kActionTextEnabled);
+  EXPECT_TRUE(action_view->GetEnabled());
+}
+
+// Test reassigning action view.
+TEST_F(ActionViewControllerTest, TestReassignActionView) {
+  std::unique_ptr<actions::ActionItem> action_item = CreateDisabledActionItem();
+  auto first_action_view = std::make_unique<MdTextButton>();
+  auto action_view_controller =
+      std::make_unique<ActionViewController<MdTextButton>>(
+          first_action_view.get(), action_item->GetAsWeakPtr());
+  EXPECT_EQ(first_action_view->GetText(), kActionTextDisabled);
+  EXPECT_FALSE(first_action_view->GetEnabled());
+  auto second_action_view = std::make_unique<MdTextButton>();
+  action_view_controller->SetActionView(second_action_view.get());
+  action_item->SetEnabled(true);
+  EXPECT_FALSE(first_action_view->GetEnabled());
+  EXPECT_TRUE(second_action_view->GetEnabled());
+}
+
+// Test that a destroyed view does not cause crashes when action item change
+// triggered.
+TEST_F(ActionViewControllerTest, TestActionViewDestroyed) {
+  std::unique_ptr<actions::ActionItem> action_item = CreateDisabledActionItem();
+  auto action_view = std::make_unique<MdTextButton>();
+  auto action_view_controller =
+      std::make_unique<ActionViewController<MdTextButton>>(
+          action_view.get(), action_item->GetAsWeakPtr());
+  action_view.reset();
+  action_item->SetEnabled(true);
+}
+
+// Test that action triggered callbacks get called.
+TEST_F(ActionViewControllerTest, TriggerAction) {
+  std::unique_ptr<actions::ActionItem> action_item = CreateEnabledActionItem();
+  auto action_view = std::make_unique<MdTextButton>();
+  auto action_view_controller =
+      std::make_unique<ActionViewController<MdTextButton>>(
+          action_view.get(), action_item->GetAsWeakPtr());
+  action_view_controller->SetActionItem(action_item->GetAsWeakPtr());
+  EXPECT_EQ(0, action_item->GetInvokeCount());
+  ui::MouseEvent e(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                   ui::EventTimeForNow(), 0, 0);
+  views::test::ButtonTestApi test_api(action_view.get());
+  test_api.NotifyClick(e);
+  EXPECT_EQ(1, action_item->GetInvokeCount());
+}
+
+}  // namespace views
diff --git a/ui/views/controls/button/button.cc b/ui/views/controls/button/button.cc
index 36ab7de..c5764b4 100644
--- a/ui/views/controls/button/button.cc
+++ b/ui/views/controls/button/button.cc
@@ -20,6 +20,7 @@
 #include "ui/gfx/animation/throb_animation.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/native_theme/native_theme.h"
+#include "ui/views/action_view_controller.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/animation/ink_drop_highlight.h"
 #include "ui/views/animation/ink_drop_impl.h"
@@ -777,6 +778,13 @@
   }
 }
 
+// TOOD(crbug.com/147023): Implement ActionItemChangedImpl for
+// ButtonActionViewController.
+template <>
+void ActionViewController<Button, ActionViewController<View>>::
+    ActionItemChangedImpl(Button* action_view,
+                          actions::ActionItem* action_item) {}
+
 BEGIN_METADATA(Button)
 ADD_PROPERTY_METADATA(PressedCallback, Callback)
 ADD_PROPERTY_METADATA(bool, AnimateOnStateChange)
diff --git a/ui/views/controls/button/button.h b/ui/views/controls/button/button.h
index bfb1065..d10a7ec2 100644
--- a/ui/views/controls/button/button.h
+++ b/ui/views/controls/button/button.h
@@ -16,6 +16,7 @@
 #include "ui/events/event_constants.h"
 #include "ui/gfx/animation/throb_animation.h"
 #include "ui/native_theme/native_theme.h"
+#include "ui/views/action_view_controller.h"
 #include "ui/views/animation/animation_delegate_views.h"
 #include "ui/views/animation/ink_drop_host.h"
 #include "ui/views/animation/ink_drop_state.h"
@@ -23,8 +24,10 @@
 #include "ui/views/controls/focus_ring.h"
 #include "ui/views/metadata/view_factory.h"
 #include "ui/views/painter.h"
+#include "ui/views/view.h"
 
 namespace views {
+
 namespace test {
 class ButtonTestApi;
 }
@@ -382,6 +385,16 @@
   base::WeakPtrFactory<Button> weak_ptr_factory_{this};
 };
 
+template <>
+struct ActionViewControllerSuperClassT<Button> {
+  using SuperClass = ActionViewController<View>;
+};
+
+template <>
+void ActionViewController<Button, ActionViewController<View>>::
+    ActionItemChangedImpl(Button* action_view,
+                          actions::ActionItem* action_item);
+
 BEGIN_VIEW_BUILDER(VIEWS_EXPORT, Button, View)
 VIEW_BUILDER_PROPERTY(Button::PressedCallback, Callback)
 VIEW_BUILDER_PROPERTY(base::TimeDelta, AnimationDuration)
diff --git a/ui/views/controls/button/md_text_button.cc b/ui/views/controls/button/md_text_button.cc
index a1bbf3d..891bf9e14 100644
--- a/ui/views/controls/button/md_text_button.cc
+++ b/ui/views/controls/button/md_text_button.cc
@@ -21,6 +21,7 @@
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/native_theme/native_theme.h"
+#include "ui/views/action_view_controller.h"
 #include "ui/views/animation/flood_fill_ink_drop_ripple.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/animation/ink_drop_highlight.h"
@@ -346,6 +347,25 @@
   }
 }
 
+template <>
+void ActionViewController<MdTextButton, ActionViewController<Button>>::
+    ActionItemChangedImpl(MdTextButton* action_view,
+                          actions::ActionItem* action_item) {
+  action_view->SetText(action_item->GetText());
+  action_view->SetTooltipText(action_item->GetTooltipText());
+  action_view->SetImageModel(Button::ButtonState::STATE_NORMAL,
+                             action_item->GetImage());
+}
+
+template <>
+void ActionViewController<MdTextButton, ActionViewController<Button>>::
+    SetActionViewImpl(MdTextButton* action_view) {
+  if (action_view) {
+    action_view->SetCallback(base::BindRepeating(
+        &ActionViewController::TriggerAction, base::Unretained(this)));
+  }
+}
+
 BEGIN_METADATA(MdTextButton, LabelButton)
 ADD_PROPERTY_METADATA(bool, Prominent)
 ADD_PROPERTY_METADATA(absl::optional<float>, CornerRadius)
diff --git a/ui/views/controls/button/md_text_button.h b/ui/views/controls/button/md_text_button.h
index 61b9e1a..0e2bc0fa 100644
--- a/ui/views/controls/button/md_text_button.h
+++ b/ui/views/controls/button/md_text_button.h
@@ -9,12 +9,17 @@
 
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/ui_base_types.h"
+#include "ui/views/action_view_controller.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/focus_ring.h"
 #include "ui/views/style/typography.h"
 
 namespace views {
 
+// TODO(crbug.com/147023): Remove when ActionViewController implementation adds
+// LabelButton.
+class Button;
+
 // A button class that implements the Material Design text button spec.
 class VIEWS_EXPORT MdTextButton : public LabelButton {
  public:
@@ -90,6 +95,20 @@
   absl::optional<gfx::Insets> custom_padding_;
 };
 
+template <>
+struct VIEWS_EXPORT ActionViewControllerSuperClassT<MdTextButton> {
+  using SuperClass = ActionViewController<Button>;
+};
+
+template <>
+void ActionViewController<MdTextButton, ActionViewController<Button>>::
+    ActionItemChangedImpl(MdTextButton* action_view,
+                          actions::ActionItem* action_item);
+
+template <>
+void ActionViewController<MdTextButton, ActionViewController<Button>>::
+    SetActionViewImpl(MdTextButton* action_view);
+
 BEGIN_VIEW_BUILDER(VIEWS_EXPORT, MdTextButton, LabelButton)
 VIEW_BUILDER_PROPERTY(bool, Prominent)
 VIEW_BUILDER_PROPERTY(absl::optional<float>, CornerRadius)
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 9b0b1c6..2dda88c6 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -1513,10 +1513,11 @@
   if (pending_item_changed)
     StopShowTimer();
 
-  if (selection_types & SELECTION_UPDATE_IMMEDIATELY)
+  if (selection_types & SELECTION_UPDATE_IMMEDIATELY) {
     CommitPendingSelection();
-  else if (pending_item_changed)
+  } else if (pending_item_changed) {
     StartShowTimer();
+  }
 
   // Notify an accessibility focus event on all menu items except for the root.
   if (menu_item && pending_item_changed &&
@@ -1536,7 +1537,7 @@
         menu_item->GetParentMenuItem()->GetSubmenu()) {
       menu_item->GetParentMenuItem()->GetSubmenu()->NotifyAccessibilityEvent(
           ax::mojom::Event::kSelectedChildrenChanged,
-          true /* send_native_event */);
+          /*send_native_event=*/true);
     }
   }
 }
diff --git a/ui/views/examples/actions_example.cc b/ui/views/examples/actions_example.cc
index 4a19241a..51fce12 100644
--- a/ui/views/examples/actions_example.cc
+++ b/ui/views/examples/actions_example.cc
@@ -14,7 +14,9 @@
 #include "base/functional/callback.h"
 #include "base/scoped_observation.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/actions/action_id.h"
 #include "ui/actions/actions.h"
@@ -27,6 +29,7 @@
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/views/action_view_controller.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/button/md_text_button.h"
@@ -50,93 +53,6 @@
 
 namespace views::examples {
 
-class ActionButton : public MdTextButton {
- public:
-  METADATA_HEADER(ActionButton);
-  explicit ActionButton(actions::ActionItem* action_item = nullptr,
-                        int button_context = style::CONTEXT_BUTTON_MD);
-  ActionButton(const ActionButton&) = delete;
-  ActionButton& operator=(const ActionButton&) = delete;
-  ~ActionButton() override = default;
-  actions::ActionItem* GetActionItem() const;
-  void SetActionItem(actions::ActionItem* action_item);
-  std::u16string GetName() const;
-  void SetName(const std::u16string& name);
-
- private:
-  void ActionItemChanged();
-  void TriggerAction();
-  std::u16string name_;
-  raw_ptr<actions::ActionItem> action_item_ = nullptr;
-  base::CallbackListSubscription action_changed_subscription_;
-};
-
-ActionButton::ActionButton(actions::ActionItem* action_item, int button_context)
-    : MdTextButton(base::BindRepeating(&ActionButton::TriggerAction,
-                                       base::Unretained(this)),
-                   std::u16string(),
-                   button_context) {
-  SetActionItem(action_item);
-}
-
-actions::ActionItem* ActionButton::GetActionItem() const {
-  return action_item_.get();
-}
-
-void ActionButton::SetActionItem(actions::ActionItem* action_item) {
-  if (action_item_.get() == action_item) {
-    return;
-  }
-  action_item_ = action_item;
-  action_changed_subscription_ = {};
-  if (action_item_) {
-    action_changed_subscription_ =
-        action_item_->AddActionChangedCallback(base::BindRepeating(
-            &ActionButton::ActionItemChanged, base::Unretained(this)));
-    ActionItemChanged();
-  }
-  OnPropertyChanged(&action_item_,
-                    static_cast<PropertyEffects>(kPropertyEffectsLayout |
-                                                 kPropertyEffectsPaint));
-}
-
-std::u16string ActionButton::GetName() const {
-  return name_;
-}
-
-void ActionButton::SetName(const std::u16string& name) {
-  if (name == name_) {
-    return;
-  }
-  name_ = name;
-  if (GetText().empty()) {
-    SetText(name_);
-  }
-  OnPropertyChanged(&name, kPropertyEffectsNone);
-}
-
-void ActionButton::ActionItemChanged() {
-  SetText(action_item_->GetText());
-  SetEnabled(action_item_->GetEnabled());
-  SetVisible(action_item_->GetVisible());
-  SetTooltipText(action_item_->GetTooltipText());
-  SetImageModel(Button::ButtonState::STATE_NORMAL, action_item_->GetImage());
-}
-
-void ActionButton::TriggerAction() {
-  if (action_item_.get()) {
-    action_item_->InvokeAction();
-  }
-}
-
-BEGIN_METADATA(ActionButton, MdTextButton)
-END_METADATA
-
-BEGIN_VIEW_BUILDER(, ActionButton, MdTextButton)
-VIEW_BUILDER_PROPERTY(actions::ActionItem*, ActionItem)
-VIEW_BUILDER_PROPERTY(std::u16string, Name)
-END_VIEW_BUILDER
-
 class ActionCheckbox : public Checkbox {
  public:
   METADATA_HEADER(ActionCheckbox);
@@ -223,7 +139,6 @@
 
 }  // namespace views::examples
 
-DEFINE_VIEW_BUILDER(, views::examples::ActionButton)
 DEFINE_VIEW_BUILDER(, views::examples::ActionCheckbox)
 
 namespace views::examples {
@@ -285,8 +200,10 @@
 std::u16string ViewsComboboxModel::GetItemAt(size_t index) const {
   if (container_->children().size()) {
     View* view = container_->children()[index];
-    if (IsViewClass<ActionButton>(view)) {
-      return AsViewClass<ActionButton>(view)->GetName();
+    if (IsViewClass<MdTextButton>(view)) {
+      std::stringstream ss;
+      ss << index;
+      return base::ASCIIToUTF16(base::StringPiece("Button: " + ss.str()));
     }
     if (IsViewClass<ActionCheckbox>(view)) {
       return AsViewClass<ActionCheckbox>(view)->GetName();
@@ -486,13 +403,17 @@
 
   auto add_combobox_and_button = [&add_combobox_row](
                                      std::unique_ptr<ui::ComboboxModel> model,
+                                     ActionViewController<MdTextButton>*
+                                         action_button_view_controller,
                                      int label_text,
                                      actions::ActionId action_id) {
     auto pair = add_combobox_row(std::move(model), label_text);
+    views::MdTextButton* action_button;
     pair.first->AddChildView(
-        Builder<ActionButton>()
-            .SetActionItem(actions::ActionManager::Get().FindAction(action_id))
-            .Build());
+        Builder<MdTextButton>().CopyAddressTo(&action_button).Build());
+    action_button_view_controller->SetActionView(action_button);
+    action_button_view_controller->SetActionItem(
+        actions::ActionManager::Get().FindAction(action_id)->GetAsWeakPtr());
     return pair.second;
   };
 
@@ -538,10 +459,16 @@
     return textfield;
   };
 
+  auto available_controls_view_controller =
+      std::make_unique<ActionViewController<MdTextButton>>();
+
   available_controls_ =
       add_combobox_and_button(std::make_unique<ControlTypeComboboxModel>(),
+                              available_controls_view_controller.get(),
                               IDS_AVAILABLE_CONTROLS, kActionCreateControl);
 
+  action_view_controllers_.push_back(
+      std::move(available_controls_view_controller));
   control_panel_->AddChildView(
       Builder<Separator>().SetProperty(kMarginsKey, kSeparatorPadding).Build());
 
@@ -550,9 +477,14 @@
                   IDS_CONTROLS)
                   .second;
 
+  auto available_actions_view_controller =
+      std::make_unique<ActionViewController<MdTextButton>>();
   available_actions_ = add_combobox_and_button(
       std::make_unique<ActionItemComboboxModel>(example_actions_.get()),
-      IDS_AVAILABLE_ACTIONS, kActionAssignAction);
+      available_actions_view_controller.get(), IDS_AVAILABLE_ACTIONS,
+      kActionAssignAction);
+  action_view_controllers_.push_back(
+      std::move(available_actions_view_controller));
   subscriptions_.push_back(
       available_actions_->AddSelectedIndexChangedCallback(base::BindRepeating(
           &ActionsExample::ActionSelected, base::Unretained(this))));
@@ -664,10 +596,12 @@
   }
   ViewsComboboxModel* model =
       static_cast<ViewsComboboxModel*>(controls_->GetModel());
-  View* view = model->GetViewItemAt(index.value());
-  if (IsViewClass<ActionButton>(view)) {
-    ActionButton* button = AsViewClass<ActionButton>(view);
-    button->SetActionItem(GetSelectedAction());
+  size_t index_val = index.value();
+  View* view = model->GetViewItemAt(index_val);
+  if (IsViewClass<MdTextButton>(view)) {
+    auto mdtextbutton_vc = std::make_unique<ActionViewController<MdTextButton>>(
+        static_cast<MdTextButton*>(view), GetSelectedAction()->GetAsWeakPtr());
+    action_view_controllers_.push_back(std::move(mdtextbutton_vc));
   } else if (IsViewClass<ActionCheckbox>(view)) {
     ActionCheckbox* checkbox = AsViewClass<ActionCheckbox>(view);
     checkbox->SetActionItem(GetSelectedAction());
@@ -682,8 +616,8 @@
       available_controls_->GetSelectedIndex();
   switch (selected_index.value_or(0)) {
     case 0:
-      new_view = Builder<ActionButton>()
-                     .SetName(u"Button " + base::NumberToString16(control_num))
+      new_view = Builder<MdTextButton>()
+                     .SetText(u"Button " + base::NumberToString16(control_num))
                      .Build();
       break;
     case 1:
diff --git a/ui/views/examples/actions_example.h b/ui/views/examples/actions_example.h
index 1b86bc9..c594b55 100644
--- a/ui/views/examples/actions_example.h
+++ b/ui/views/examples/actions_example.h
@@ -5,13 +5,18 @@
 #ifndef UI_VIEWS_EXAMPLES_ACTIONS_EXAMPLE_H_
 #define UI_VIEWS_EXAMPLES_ACTIONS_EXAMPLE_H_
 
+#include <memory>
 #include <vector>
 
 #include "base/callback_list.h"
 #include "base/memory/raw_ptr.h"
 #include "ui/actions/actions.h"
+#include "ui/views/action_view_controller.h"
+#include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/examples/example_base.h"
+#include "ui/views/view.h"
+#include "ui/views/view_tracker.h"
 
 namespace views {
 
@@ -20,7 +25,6 @@
 class Combobox;
 class Textarea;
 class Textfield;
-class View;
 
 namespace examples {
 
@@ -50,6 +54,11 @@
   void TooltipTextChanged();
   void VisibleChanged();
 
+  // TODO(crbug.com/1472023): Instead of client having this vector we should
+  // abstract it such that an ActionViewController actually can create an manage
+  // each of the individual objects.
+  std::vector<std::unique_ptr<ActionViewController<View>>>
+      action_view_controllers_;
   std::vector<base::CallbackListSubscription> subscriptions_;
   raw_ptr<actions::ActionItem> example_actions_ = nullptr;
   raw_ptr<View> action_panel_ = nullptr;
diff --git a/ui/views/features.gni b/ui/views/features.gni
index 17bd5d9b..a4e4a53 100644
--- a/ui/views/features.gni
+++ b/ui/views/features.gni
@@ -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("//build/config/chromecast_build.gni")
+import("//build/config/cast.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/ui.gni")
 
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 1d14b7b..fd36051f 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -3698,6 +3698,14 @@
   return preferred_height;
 }
 
+template <>
+void ActionViewController<View, ActionController>::ActionItemChangedImpl(
+    View* action_view,
+    actions::ActionItem* action_item) {
+  action_view->SetEnabled(action_item->GetEnabled());
+  action_view->SetVisible(action_item->GetVisible());
+}
+
 // This block requires the existence of METADATA_HEADER(View) in the class
 // declaration for View.
 BEGIN_METADATA_BASE(View)
diff --git a/ui/views/view.h b/ui/views/view.h
index 6cfd912..08ee427 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -50,6 +50,7 @@
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
 #include "ui/gfx/native_widget_types.h"
+#include "ui/views/action_view_controller.h"
 #include "ui/views/layout/layout_manager.h"
 #include "ui/views/layout/layout_types.h"
 #include "ui/views/metadata/view_factory.h"
@@ -2422,6 +2423,16 @@
   LifeCycleState life_cycle_state_ = LifeCycleState::kAlive;
 };
 
+template <>
+struct ActionViewControllerSuperClassT<View> {
+  using SuperClass = ActionController;
+};
+
+template <>
+void ActionViewController<View, ActionController>::ActionItemChangedImpl(
+    View* action_view,
+    actions::ActionItem* action_item);
+
 BEGIN_VIEW_BUILDER(VIEWS_EXPORT, View, BaseView)
 template <typename LayoutManager>
 BuilderT& SetLayoutManager(std::unique_ptr<LayoutManager> layout_manager) & {
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index 968eeba..4f7fe0ed1 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -1780,8 +1780,9 @@
           // process it.
           (event->flags() &
            (ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON |
-            ui::EF_RIGHT_MOUSE_BUTTON)) != 0)
+            ui::EF_RIGHT_MOUSE_BUTTON)) != 0) {
         event->SetHandled();
+      }
       return;
 
     case ui::ET_MOUSE_MOVED:
diff --git a/ui/webui/resources/cr_components/app_management/app_management.mojom b/ui/webui/resources/cr_components/app_management/app_management.mojom
index eab50dbc..cf99aa5 100644
--- a/ui/webui/resources/cr_components/app_management/app_management.mojom
+++ b/ui/webui/resources/cr_components/app_management/app_management.mojom
@@ -200,9 +200,9 @@
   OpenNativeSettings(string app_id);
   // On ChromeOS, this updates the preferred apps list for `app_id`.
   // On Windows, Mac and Linux, this is used to update the
-  // is_user_selected_app_for_capturing_links_ flag on the web_app DB
+  // user_link_capturing_preference_ flag on the web_app DB
   // for the `app_id`. If the app_id is set as a preferred app,
-  // then it resets is_user_selected_app_for_capturing_links_
+  // then it resets user_link_capturing_preference_
   // for all other apps if that is set.
   SetPreferredApp(string app_id, bool is_preferred_app);
   // On ChromeOS: Returns a list of |app_ids| that are currently set
diff --git a/ui/webui/resources/cr_components/omnibox/realbox_icon.html b/ui/webui/resources/cr_components/omnibox/realbox_icon.html
index 4758eb8..aff17ed9 100644
--- a/ui/webui/resources/cr_components/omnibox/realbox_icon.html
+++ b/ui/webui/resources/cr_components/omnibox/realbox_icon.html
@@ -107,6 +107,10 @@
     -webkit-mask-size: 20px;  /* Loupe in realbox is larger than in matches. */
   }
 
+  :host([in-searchbox][mask-image*='//resources/cr_components/omnibox/icons/search_cr23.svg']) #icon {
+    -webkit-mask-size: 20px;  /* Loupe in realbox is larger than in matches. */
+  }
+
   :host([has-icon-container-background]:not([in-searchbox])) #icon {
     background-color: #041E49;
   }
diff --git a/ui/webui/resources/js/test_loader_util.ts b/ui/webui/resources/js/test_loader_util.ts
index 0b3f1f09..15468a3 100644
--- a/ui/webui/resources/js/test_loader_util.ts
+++ b/ui/webui/resources/js/test_loader_util.ts
@@ -6,8 +6,11 @@
     window.trustedTypes!.createPolicy('webui-test-script', {
       createHTML: () => '',
       createScriptURL: urlString => {
-        const url = new URL(urlString);
-        if (url.protocol === 'chrome:') {
+        // Ensure this is a scheme-relative URL requested by a chrome or
+        // chrome-untrusted host.
+        const url = new URL(window.location.href);
+        if (['chrome:', 'chrome-untrusted:'].includes(url.protocol) &&
+            urlString.startsWith('//')) {
           return urlString;
         }
 
@@ -49,7 +52,7 @@
     return Promise.resolve(false);
   }
 
-  await loadScript(`chrome://webui-test/${module}`);
+  await loadScript(`//webui-test/${module}`);
   return Promise.resolve(true);
 }
 
@@ -60,6 +63,6 @@
     return Promise.reject(new Error(`Invalid adapter=${adapter} parameter`));
   }
 
-  await loadScript(`chrome://webui-test/${adapter}`);
+  await loadScript(`//webui-test/${adapter}`);
   return Promise.resolve(true);
 }
diff --git a/ui/webui/resources/mojo/BUILD.gn b/ui/webui/resources/mojo/BUILD.gn
index de4c48b..d58cfbd 100644
--- a/ui/webui/resources/mojo/BUILD.gn
+++ b/ui/webui/resources/mojo/BUILD.gn
@@ -11,22 +11,6 @@
 
 tsc_folder = "$root_gen_dir/ui/webui/resources/tsc/mojo"
 
-mojo_js_files = [
-  "mojo/public/mojom/base/big_buffer.mojom-webui.js",
-  "mojo/public/mojom/base/file.mojom-webui.js",
-  "mojo/public/mojom/base/file_path.mojom-webui.js",
-  "mojo/public/mojom/base/int128.mojom-webui.js",
-  "mojo/public/mojom/base/process_id.mojom-webui.js",
-  "mojo/public/mojom/base/read_only_buffer.mojom-webui.js",
-  "mojo/public/mojom/base/safe_base_name.mojom-webui.js",
-  "mojo/public/mojom/base/string16.mojom-webui.js",
-  "mojo/public/mojom/base/text_direction.mojom-webui.js",
-  "mojo/public/mojom/base/time.mojom-webui.js",
-  "mojo/public/mojom/base/token.mojom-webui.js",
-  "mojo/public/mojom/base/unguessable_token.mojom-webui.js",
-  "mojo/public/mojom/base/values.mojom-webui.js",
-]
-
 mojo_ts_files = [
   "skia/public/mojom/skcolor.mojom-webui.ts",
   "skia/public/mojom/bitmap.mojom-webui.ts",
@@ -44,7 +28,7 @@
 }
 
 if (is_chromeos_ash) {
-  mojo_js_files += [
+  mojo_js_files = [
     "chromeos/ash/components/multidevice/mojom/multidevice_types.mojom-webui.js",
     "chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js",
     "chromeos/ash/services/cellular_setup/public/mojom/cellular_setup.mojom-webui.js",
@@ -57,6 +41,19 @@
     "chromeos/services/network_health/public/mojom/network_diagnostics.mojom-webui.js",
     "chromeos/services/network_health/public/mojom/network_health.mojom-webui.js",
     "chromeos/services/network_health/public/mojom/network_health_types.mojom-webui.js",
+    "mojo/public/mojom/base/big_buffer.mojom-webui.js",
+    "mojo/public/mojom/base/file.mojom-webui.js",
+    "mojo/public/mojom/base/file_path.mojom-webui.js",
+    "mojo/public/mojom/base/int128.mojom-webui.js",
+    "mojo/public/mojom/base/process_id.mojom-webui.js",
+    "mojo/public/mojom/base/read_only_buffer.mojom-webui.js",
+    "mojo/public/mojom/base/safe_base_name.mojom-webui.js",
+    "mojo/public/mojom/base/string16.mojom-webui.js",
+    "mojo/public/mojom/base/text_direction.mojom-webui.js",
+    "mojo/public/mojom/base/time.mojom-webui.js",
+    "mojo/public/mojom/base/token.mojom-webui.js",
+    "mojo/public/mojom/base/unguessable_token.mojom-webui.js",
+    "mojo/public/mojom/base/values.mojom-webui.js",
     "services/network/public/mojom/ip_address.mojom-webui.js",
     "url/mojom/url.mojom-webui.js",
   ]
@@ -73,7 +70,22 @@
     "ui/latency/mojom/latency_info.mojom-webui.ts",
   ]
 } else {
-  mojo_ts_files += [ "url/mojom/url.mojom-webui.ts" ]
+  mojo_ts_files += [
+    "mojo/public/mojom/base/big_buffer.mojom-webui.ts",
+    "mojo/public/mojom/base/file.mojom-webui.ts",
+    "mojo/public/mojom/base/file_path.mojom-webui.ts",
+    "mojo/public/mojom/base/int128.mojom-webui.ts",
+    "mojo/public/mojom/base/process_id.mojom-webui.ts",
+    "mojo/public/mojom/base/read_only_buffer.mojom-webui.ts",
+    "mojo/public/mojom/base/safe_base_name.mojom-webui.ts",
+    "mojo/public/mojom/base/string16.mojom-webui.ts",
+    "mojo/public/mojom/base/text_direction.mojom-webui.ts",
+    "mojo/public/mojom/base/time.mojom-webui.ts",
+    "mojo/public/mojom/base/token.mojom-webui.ts",
+    "mojo/public/mojom/base/unguessable_token.mojom-webui.ts",
+    "mojo/public/mojom/base/values.mojom-webui.ts",
+    "url/mojom/url.mojom-webui.ts",
+  ]
 }
 
 preprocess_if_expr("copy_mojo_ts") {
@@ -102,22 +114,23 @@
       "//ui/latency/mojom:mojom_ts__generator",
     ]
   } else {
-    deps += [ "//url/mojom:url_mojom_gurl_ts__generator" ]
+    deps += [
+      "//mojo/public/mojom/base:base_ts__generator",
+      "//url/mojom:url_mojom_gurl_ts__generator",
+    ]
   }
 }
 
-# Move all the files out of mojom-webui to the expected location.
-preprocess_if_expr("copy_mojo") {
-  visibility = [ ":build_ts" ]
+if (is_chromeos_ash) {
+  # Move all the files out of mojom-webui to the expected location.
+  preprocess_if_expr("copy_mojo") {
+    visibility = [ ":build_ts" ]
 
-  in_folder = "$root_gen_dir/mojom-webui"
-  out_folder = "$target_gen_dir/preprocessed"
-  in_files = mojo_js_files
+    in_folder = "$root_gen_dir/mojom-webui"
+    out_folder = "$target_gen_dir/preprocessed"
+    in_files = mojo_js_files
 
-  deps = [ "//mojo/public/mojom/base:base_js__generator" ]
-
-  if (is_chromeos_ash) {
-    deps += [
+    deps = [
       "//chromeos/ash/components/multidevice/mojom:mojom_js__generator",
       "//chromeos/ash/services/bluetooth_config/public/mojom:mojom_js__generator",
       "//chromeos/ash/services/cellular_setup/public/mojom:mojom_js__generator",
@@ -127,6 +140,7 @@
       "//chromeos/services/network_config/public/mojom:network_types_js__generator",
       "//chromeos/services/network_health/public/mojom:mojom_js__generator",
       "//chromeos/services/network_health/public/mojom:types_js__generator",
+      "//mojo/public/mojom/base:base_js__generator",
       "//services/network/public/mojom:mojom_ip_address_js__generator",
       "//url/mojom:url_mojom_gurl_js__generator",
     ]
@@ -138,17 +152,20 @@
   out_dir = tsc_folder
   composite = true
 
-  in_files = mojo_js_files + mojo_ts_files
+  in_files = mojo_ts_files
+
+  if (is_chromeos_ash) {
+    in_files += mojo_js_files
+  }
 
   definitions = [ "$tsc_folder/mojo/public/js/bindings.d.ts" ]
 
   extra_deps = [
     ":copy_bindings_dts",
-    ":copy_mojo",
     ":copy_mojo_ts",
   ]
   if (is_chromeos_ash) {
-    extra_deps += [ ":copy_mojo_ts" ]
+    extra_deps += [ ":copy_mojo" ]
   }
 
   path_mappings = [ "//resources/mojo/*|" +
diff --git a/ui/webui/resources/test_loader.html b/ui/webui/resources/test_loader.html
index c7257ae6..c69a2f4 100644
--- a/ui/webui/resources/test_loader.html
+++ b/ui/webui/resources/test_loader.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <body>
-  <script src="chrome://webui-test/mocha.js"></script>
+  <script src="//webui-test/mocha.js"></script>
   <script type="module" src="test_loader.js"></script>
 </body>
 </html>
diff --git a/v8 b/v8
index 4eb5d72..9f07854 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit 4eb5d72079603bd00a71b6b2a75a4f1ee7637e72
+Subproject commit 9f07854eb0b779fa46b8b64bbc1da4e4a7572878